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"
452 "# ifdef HASTEXTUREGATHER\n"
453 "# extension GL_ARB_texture_gather : enable\n"
455 "# ifdef HASTEXTURE4\n"
456 "# extension GL_AMD_texture_texture4 : enable\n"
457 "# define textureGather texture4\n"
462 "// common definitions between vertex shader and fragment shader:\n"
464 "//#ifdef __GLSL_CG_DATA_TYPES\n"
465 "//# define myhalf half\n"
466 "//# define myhalf2 half2\n"
467 "//# define myhalf3half3\n"
468 "//# define myhalf4 half4\n"
470 "# define myhalf float\n"
471 "# define myhalf2 vec2\n"
472 "# define myhalf3 vec3\n"
473 "# define myhalf4 vec4\n"
476 "#ifdef MODE_DEPTH_OR_SHADOW\n"
478 "# ifdef VERTEX_SHADER\n"
481 " gl_Position = ftransform();\n"
486 "#ifdef MODE_SHOWDEPTH\n"
487 "# ifdef VERTEX_SHADER\n"
490 " gl_Position = ftransform();\n"
491 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
494 "# ifdef FRAGMENT_SHADER\n"
497 " gl_FragColor = gl_Color;\n"
501 "#else // !MODE_SHOWDEPTH\n"
503 "#ifdef MODE_POSTPROCESS\n"
504 "# ifdef VERTEX_SHADER\n"
507 " gl_FrontColor = gl_Color;\n"
508 " gl_Position = ftransform();\n"
509 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
511 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
515 "# ifdef FRAGMENT_SHADER\n"
517 "uniform sampler2D Texture_First;\n"
519 "uniform sampler2D Texture_Second;\n"
521 "#ifdef USEGAMMARAMPS\n"
522 "uniform sampler2D Texture_GammaRamps;\n"
524 "#ifdef USESATURATION\n"
525 "uniform float Saturation;\n"
527 "#ifdef USEVIEWTINT\n"
528 "uniform vec4 TintColor;\n"
530 "//uncomment these if you want to use them:\n"
531 "uniform vec4 UserVec1;\n"
532 "// uniform vec4 UserVec2;\n"
533 "// uniform vec4 UserVec3;\n"
534 "// uniform vec4 UserVec4;\n"
535 "// uniform float ClientTime;\n"
536 "uniform vec2 PixelSize;\n"
539 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
541 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
543 "#ifdef USEVIEWTINT\n"
544 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
547 "#ifdef USEPOSTPROCESSING\n"
548 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
549 "// 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"
550 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
551 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
552 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
553 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
554 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
555 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
558 "#ifdef USESATURATION\n"
559 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
560 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
561 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
562 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
565 "#ifdef USEGAMMARAMPS\n"
566 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
567 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
568 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
575 "#ifdef MODE_GENERIC\n"
576 "# ifdef VERTEX_SHADER\n"
579 " gl_FrontColor = gl_Color;\n"
580 "# ifdef USEDIFFUSE\n"
581 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
583 "# ifdef USESPECULAR\n"
584 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
586 " gl_Position = ftransform();\n"
589 "# ifdef FRAGMENT_SHADER\n"
591 "# ifdef USEDIFFUSE\n"
592 "uniform sampler2D Texture_First;\n"
594 "# ifdef USESPECULAR\n"
595 "uniform sampler2D Texture_Second;\n"
600 " gl_FragColor = gl_Color;\n"
601 "# ifdef USEDIFFUSE\n"
602 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
605 "# ifdef USESPECULAR\n"
606 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
608 "# ifdef USECOLORMAPPING\n"
609 " gl_FragColor *= tex2;\n"
612 " gl_FragColor += tex2;\n"
614 "# ifdef USEVERTEXTEXTUREBLEND\n"
615 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
620 "#else // !MODE_GENERIC\n"
622 "varying vec2 TexCoord;\n"
623 "#ifdef USEVERTEXTEXTUREBLEND\n"
624 "varying vec2 TexCoord2;\n"
626 "varying vec2 TexCoordLightmap;\n"
628 "#ifdef MODE_LIGHTSOURCE\n"
629 "varying vec3 CubeVector;\n"
632 "#ifdef MODE_LIGHTSOURCE\n"
633 "varying vec3 LightVector;\n"
635 "#ifdef MODE_LIGHTDIRECTION\n"
636 "varying vec3 LightVector;\n"
639 "varying vec3 EyeVector;\n"
641 "varying vec3 EyeVectorModelSpace;\n"
644 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
645 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
646 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
648 "#ifdef MODE_WATER\n"
649 "varying vec4 ModelViewProjectionPosition;\n"
651 "#ifdef MODE_REFRACTION\n"
652 "varying vec4 ModelViewProjectionPosition;\n"
654 "#ifdef USEREFLECTION\n"
655 "varying vec4 ModelViewProjectionPosition;\n"
662 "// vertex shader specific:\n"
663 "#ifdef VERTEX_SHADER\n"
665 "uniform vec3 LightPosition;\n"
666 "uniform vec3 EyePosition;\n"
667 "uniform vec3 LightDir;\n"
669 "// 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"
673 " gl_FrontColor = gl_Color;\n"
674 " // copy the surface texcoord\n"
675 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
676 "#ifdef USEVERTEXTEXTUREBLEND\n"
677 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
679 "#ifndef MODE_LIGHTSOURCE\n"
680 "# ifndef MODE_LIGHTDIRECTION\n"
681 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
685 "#ifdef MODE_LIGHTSOURCE\n"
686 " // transform vertex position into light attenuation/cubemap space\n"
687 " // (-1 to +1 across the light box)\n"
688 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
690 " // transform unnormalized light direction into tangent space\n"
691 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
692 " // normalize it per pixel)\n"
693 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
694 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
695 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
696 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
699 "#ifdef MODE_LIGHTDIRECTION\n"
700 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
701 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
702 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
705 " // transform unnormalized eye direction into tangent space\n"
707 " vec3 EyeVectorModelSpace;\n"
709 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
710 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
711 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
712 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
714 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
715 " VectorS = gl_MultiTexCoord1.xyz;\n"
716 " VectorT = gl_MultiTexCoord2.xyz;\n"
717 " VectorR = gl_MultiTexCoord3.xyz;\n"
720 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
721 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
722 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
723 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
726 "// transform vertex to camera space, using ftransform to match non-VS\n"
728 " gl_Position = ftransform();\n"
730 "#ifdef MODE_WATER\n"
731 " ModelViewProjectionPosition = gl_Position;\n"
733 "#ifdef MODE_REFRACTION\n"
734 " ModelViewProjectionPosition = gl_Position;\n"
736 "#ifdef USEREFLECTION\n"
737 " ModelViewProjectionPosition = gl_Position;\n"
741 "#endif // VERTEX_SHADER\n"
746 "// fragment shader specific:\n"
747 "#ifdef FRAGMENT_SHADER\n"
749 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
750 "uniform sampler2D Texture_Normal;\n"
751 "uniform sampler2D Texture_Color;\n"
752 "uniform sampler2D Texture_Gloss;\n"
753 "uniform sampler2D Texture_Glow;\n"
754 "uniform sampler2D Texture_SecondaryNormal;\n"
755 "uniform sampler2D Texture_SecondaryColor;\n"
756 "uniform sampler2D Texture_SecondaryGloss;\n"
757 "uniform sampler2D Texture_SecondaryGlow;\n"
758 "uniform sampler2D Texture_Pants;\n"
759 "uniform sampler2D Texture_Shirt;\n"
760 "uniform sampler2D Texture_FogMask;\n"
761 "uniform sampler2D Texture_Lightmap;\n"
762 "uniform sampler2D Texture_Deluxemap;\n"
763 "uniform sampler2D Texture_Refraction;\n"
764 "uniform sampler2D Texture_Reflection;\n"
765 "uniform sampler2D Texture_Attenuation;\n"
766 "uniform samplerCube Texture_Cube;\n"
768 "#define showshadowmap 0\n"
770 "#ifdef USESHADOWMAPRECT\n"
771 "# ifdef USESHADOWSAMPLER\n"
772 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
774 "uniform sampler2DRect Texture_ShadowMapRect;\n"
777 "uniform samplerCube Texture_CubeProjection;\n"
780 "uniform myhalf3 LightColor;\n"
781 "uniform myhalf3 AmbientColor;\n"
782 "uniform myhalf3 DiffuseColor;\n"
783 "uniform myhalf3 SpecularColor;\n"
784 "uniform myhalf3 Color_Pants;\n"
785 "uniform myhalf3 Color_Shirt;\n"
786 "uniform myhalf3 FogColor;\n"
788 "uniform myhalf4 TintColor;\n"
791 "//#ifdef MODE_WATER\n"
792 "uniform vec4 DistortScaleRefractReflect;\n"
793 "uniform vec4 ScreenScaleRefractReflect;\n"
794 "uniform vec4 ScreenCenterRefractReflect;\n"
795 "uniform myhalf4 RefractColor;\n"
796 "uniform myhalf4 ReflectColor;\n"
797 "uniform myhalf ReflectFactor;\n"
798 "uniform myhalf ReflectOffset;\n"
800 "//# ifdef MODE_REFRACTION\n"
801 "//uniform vec4 DistortScaleRefractReflect;\n"
802 "//uniform vec4 ScreenScaleRefractReflect;\n"
803 "//uniform vec4 ScreenCenterRefractReflect;\n"
804 "//uniform myhalf4 RefractColor;\n"
805 "//# ifdef USEREFLECTION\n"
806 "//uniform myhalf4 ReflectColor;\n"
809 "//# ifdef USEREFLECTION\n"
810 "//uniform vec4 DistortScaleRefractReflect;\n"
811 "//uniform vec4 ScreenScaleRefractReflect;\n"
812 "//uniform vec4 ScreenCenterRefractReflect;\n"
813 "//uniform myhalf4 ReflectColor;\n"
818 "uniform myhalf GlowScale;\n"
819 "uniform myhalf SceneBrightness;\n"
821 "uniform float OffsetMapping_Scale;\n"
822 "uniform float OffsetMapping_Bias;\n"
823 "uniform float FogRangeRecip;\n"
825 "uniform myhalf AmbientScale;\n"
826 "uniform myhalf DiffuseScale;\n"
827 "uniform myhalf SpecularScale;\n"
828 "uniform myhalf SpecularPower;\n"
830 "#ifdef USEOFFSETMAPPING\n"
831 "vec2 OffsetMapping(vec2 TexCoord)\n"
833 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
834 " // 14 sample relief mapping: linear search and then binary search\n"
835 " // this basically steps forward a small amount repeatedly until it finds\n"
836 " // itself inside solid, then jitters forward and back using decreasing\n"
837 " // amounts to find the impact\n"
838 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
839 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
840 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
841 " vec3 RT = vec3(TexCoord, 1);\n"
842 " OffsetVector *= 0.1;\n"
843 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
844 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
845 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
846 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
847 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
848 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
849 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
850 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
851 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
852 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
853 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
854 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
855 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
856 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
859 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
860 " // this basically moves forward the full distance, and then backs up based\n"
861 " // on height of samples\n"
862 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
863 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
864 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
865 " TexCoord += OffsetVector;\n"
866 " OffsetVector *= 0.333;\n"
867 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
868 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
869 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
870 " return TexCoord;\n"
873 "#endif // USEOFFSETMAPPING\n"
875 "#ifdef USESHADOWMAPRECT \n"
876 "uniform vec4 ShadowMap_TextureScale;\n"
878 "uniform vec4 ShadowMap_Parameters;\n"
881 "vec3 GetShadowMapTC2D(vec3 dir)\n"
883 " vec3 adir = abs(dir);\n"
888 " if (adir.x > adir.y)\n"
890 " if (adir.x > adir.z)\n"
893 " if (dir.x >= 0.0)\n"
896 " tc = vec2(-dir.z, -dir.y);\n"
897 " offset = vec2(0.5, 0.5);\n"
902 " tc = vec2( dir.z, -dir.y);\n"
903 " offset = vec2(1.5, 0.5);\n"
909 " if (dir.z >= 0.0)\n"
912 " tc = vec2( dir.x, -dir.y);\n"
913 " offset = vec2(0.5, 2.5);\n"
918 " tc = vec2(-dir.x, -dir.y);\n"
919 " offset = vec2(1.5, 2.5);\n"
925 " if (adir.y > adir.z)\n"
928 " if (dir.y >= 0.0)\n"
931 " tc = vec2( dir.x, dir.z);\n"
932 " offset = vec2(0.5, 1.5);\n"
937 " tc = vec2( dir.x, -dir.z);\n"
938 " offset = vec2(1.5, 1.5);\n"
944 " if (dir.z >= 0.0)\n"
947 " tc = vec2(dir.x, -dir.y);\n"
948 " offset = vec2(0.5, 2.5);\n"
953 " tc = vec2(-dir.x, -dir.y);\n"
954 " offset = vec2(1.5, 2.5);\n"
959 " return vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma + vec3(offset * ShadowMap_Parameters.y, ShadowMap_Parameters.z);\n"
961 " return vec3(textureCube(Texture_CubeProjection, dir.xyz).ra * ShadowMap_TextureScale.xy, ShadowMap_TextureScale.z + ShadowMap_TextureScale.w / max(max(adir.x, adir.y), adir.z));\n"
965 "#endif // USESHADOWMAPRECT\n"
967 "#if !showshadowmap\n"
968 "# ifdef USESHADOWMAPRECT\n"
969 "float ShadowMapCompare(vec3 dir)\n"
971 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
973 "# ifdef USESHADOWSAMPLER\n"
975 "# ifdef USESHADOWMAPPCF\n"
976 " f = dot(vec4(0.25),\n"
977 " vec4(shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3(-0.4, 1.0, 0.0)).r,\n"
978 " shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3(-1.0, -0.4, 0.0)).r,\n"
979 " shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3( 0.4, -1.0, 0.0)).r,\n"
980 " shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3( 1.0, 0.4, 0.0)).r));\n"
982 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
987 "# ifdef USESHADOWMAPPCF\n"
988 "# if defined(HASTEXTUREGATHER) || defined(HASTEXTURE4)\n"
989 " vec2 offset = fract(shadowmaptc.xy - 0.5);\n"
990 " vec4 group1 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, -1.0))),\n"
991 " group2 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, -1.0))),\n"
992 " group3 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, 1.0))),\n"
993 " group4 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, 1.0))),\n"
994 " cols = vec4(group1.ab, group2.ab) + vec4(group3.rg, group4.rg) +\n"
995 " mix(vec4(group1.rg, group2.rg), vec4(group3.ab, group4.ab), offset.y);\n"
996 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
998 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
999 " vec4 row1 = step(shadowmaptc.z,\n"
1000 " vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, -1.0)).r,\n"
1001 " texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0, -1.0)).r,\n"
1002 " texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, -1.0)).r,\n"
1003 " texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, -1.0)).r)),\n"
1004 " row2 = step(shadowmaptc.z,\n"
1005 " vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, 0.0)).r,\n"
1006 " texture2DRect(Texture_ShadowMapRect, center).r,\n"
1007 " texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, 0.0)).r,\n"
1008 " texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, 0.0)).r)),\n"
1009 " row3 = step(shadowmaptc.z,\n"
1010 " vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, 1.0)).r,\n"
1011 " texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0, 1.0)).r,\n"
1012 " texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, 1.0)).r,\n"
1013 " texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, 1.0)).r)),\n"
1014 " row4 = step(shadowmaptc.z,\n"
1015 " vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, 2.0)).r,\n"
1016 " texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0, 2.0)).r,\n"
1017 " texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, 2.0)).r,\n"
1018 " texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, 2.0)).r)),\n"
1019 " cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1020 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1022 " vec2 offset = fract(shadowmaptc.xy);\n"
1023 " vec3 row1 = step(shadowmaptc.z,\n"
1024 " vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, -1.0)).r,\n"
1025 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 0.0, -1.0)).r,\n"
1026 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, -1.0)).r)),\n"
1027 " row2 = step(shadowmaptc.z,\n"
1028 " vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, 0.0)).r,\n"
1029 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r,\n"
1030 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, 0.0)).r)),\n"
1031 " row3 = step(shadowmaptc.z,\n"
1032 " vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, 1.0)).r,\n"
1033 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 0.0, 1.0)).r,\n"
1034 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, 1.0)).r)),\n"
1035 " cols = row2 + mix(row1, row3, offset.y);\n"
1036 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1039 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1050 "#ifdef MODE_WATER\n"
1055 "#ifdef USEOFFSETMAPPING\n"
1056 " // apply offsetmapping\n"
1057 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1058 "#define TexCoord TexCoordOffset\n"
1061 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1062 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1063 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1064 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1065 " // FIXME temporary hack to detect the case that the reflection\n"
1066 " // gets blackened at edges due to leaving the area that contains actual\n"
1068 " // Remove this 'ack once we have a better way to stop this thing from\n"
1070 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1071 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1072 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1073 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1074 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1075 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1076 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1077 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1078 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1079 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1080 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1081 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1084 "#else // !MODE_WATER\n"
1085 "#ifdef MODE_REFRACTION\n"
1087 "// refraction pass\n"
1090 "#ifdef USEOFFSETMAPPING\n"
1091 " // apply offsetmapping\n"
1092 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1093 "#define TexCoord TexCoordOffset\n"
1096 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1097 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1098 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1099 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1100 " // FIXME temporary hack to detect the case that the reflection\n"
1101 " // gets blackened at edges due to leaving the area that contains actual\n"
1103 " // Remove this 'ack once we have a better way to stop this thing from\n"
1105 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1106 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1107 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1108 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1109 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1110 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1113 "#else // !MODE_REFRACTION\n"
1116 "#ifdef USEOFFSETMAPPING\n"
1117 " // apply offsetmapping\n"
1118 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1119 "#define TexCoord TexCoordOffset\n"
1122 " // combine the diffuse textures (base, pants, shirt)\n"
1123 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1124 "#ifdef USECOLORMAPPING\n"
1125 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1127 "#ifdef USEVERTEXTEXTUREBLEND\n"
1128 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1129 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1130 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1131 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1133 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1136 "#ifdef USEDIFFUSE\n"
1137 " // get the surface normal and the gloss color\n"
1138 "# ifdef USEVERTEXTEXTUREBLEND\n"
1139 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1140 "# ifdef USESPECULAR\n"
1141 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1144 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1145 "# ifdef USESPECULAR\n"
1146 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1153 "#ifdef MODE_LIGHTSOURCE\n"
1154 " // light source\n"
1156 " // calculate surface normal, light normal, and specular normal\n"
1157 " // compute color intensity for the two textures (colormap and glossmap)\n"
1158 " // scale by light color and attenuation as efficiently as possible\n"
1159 " // (do as much scalar math as possible rather than vector math)\n"
1160 "# ifdef USEDIFFUSE\n"
1161 " // get the light normal\n"
1162 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1164 "# ifdef USESPECULAR\n"
1165 "# ifndef USEEXACTSPECULARMATH\n"
1166 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1169 " // calculate directional shading\n"
1170 "# ifdef USEEXACTSPECULARMATH\n"
1171 " 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"
1173 " 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"
1176 "# ifdef USEDIFFUSE\n"
1177 " // calculate directional shading\n"
1178 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1180 " // calculate directionless shading\n"
1181 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1185 "#ifdef USESHADOWMAPRECT\n"
1186 "#if !showshadowmap\n"
1187 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1191 "# ifdef USECUBEFILTER\n"
1192 " // apply light cubemap filter\n"
1193 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1194 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1196 "#endif // MODE_LIGHTSOURCE\n"
1201 "#ifdef MODE_LIGHTDIRECTION\n"
1202 " // directional model lighting\n"
1203 "# ifdef USEDIFFUSE\n"
1204 " // get the light normal\n"
1205 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1207 "# ifdef USESPECULAR\n"
1208 " // calculate directional shading\n"
1209 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1210 "# ifdef USEEXACTSPECULARMATH\n"
1211 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1213 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1214 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1217 "# ifdef USEDIFFUSE\n"
1219 " // calculate directional shading\n"
1220 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1222 " color.rgb *= AmbientColor;\n"
1225 "#endif // MODE_LIGHTDIRECTION\n"
1230 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1231 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1233 " // get the light normal\n"
1234 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1235 " myhalf3 diffusenormal;\n"
1236 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1237 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1238 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1239 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1240 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1241 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1242 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1243 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1244 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1245 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1246 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1247 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1248 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1249 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1250 "# ifdef USESPECULAR\n"
1251 "# ifdef USEEXACTSPECULARMATH\n"
1252 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1254 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1255 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1259 " // apply lightmap color\n"
1260 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1261 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1266 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1267 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1269 " // get the light normal\n"
1270 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1271 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1272 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1273 "# ifdef USESPECULAR\n"
1274 "# ifdef USEEXACTSPECULARMATH\n"
1275 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1277 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1278 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1282 " // apply lightmap color\n"
1283 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1284 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1289 "#ifdef MODE_LIGHTMAP\n"
1290 " // apply lightmap color\n"
1291 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1292 "#endif // MODE_LIGHTMAP\n"
1297 "#ifdef MODE_VERTEXCOLOR\n"
1298 " // apply lightmap color\n"
1299 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1300 "#endif // MODE_VERTEXCOLOR\n"
1305 "#ifdef MODE_FLATCOLOR\n"
1306 "#endif // MODE_FLATCOLOR\n"
1314 " color *= TintColor;\n"
1317 "#ifdef USEVERTEXTEXTUREBLEND\n"
1318 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1320 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1324 " color.rgb *= SceneBrightness;\n"
1326 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1328 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1331 " // 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"
1332 "#ifdef USEREFLECTION\n"
1333 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1334 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1335 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1336 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1337 " // FIXME temporary hack to detect the case that the reflection\n"
1338 " // gets blackened at edges due to leaving the area that contains actual\n"
1340 " // Remove this 'ack once we have a better way to stop this thing from\n"
1342 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1343 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1344 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1345 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1346 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1347 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1350 " gl_FragColor = vec4(color);\n"
1352 "#if showshadowmap\n"
1353 "# ifdef USESHADOWMAPRECT\n"
1354 "# ifdef USESHADOWSAMPLER\n"
1355 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1357 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1362 "#endif // !MODE_REFRACTION\n"
1363 "#endif // !MODE_WATER\n"
1365 "#endif // FRAGMENT_SHADER\n"
1367 "#endif // !MODE_GENERIC\n"
1368 "#endif // !MODE_POSTPROCESS\n"
1369 "#endif // !MODE_SHOWDEPTH\n"
1370 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1373 typedef struct shaderpermutationinfo_s
1375 const char *pretext;
1378 shaderpermutationinfo_t;
1380 typedef struct shadermodeinfo_s
1382 const char *vertexfilename;
1383 const char *geometryfilename;
1384 const char *fragmentfilename;
1385 const char *pretext;
1390 typedef enum shaderpermutation_e
1392 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1393 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1394 SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
1395 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1396 SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
1397 SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
1398 SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
1399 SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
1400 SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
1401 SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
1402 SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
1403 SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
1404 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1405 SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1406 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
1407 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1408 SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
1409 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<12, ///< (lightsource) use shadowmap cubemap texture as light filter
1410 SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
1411 SHADERPERMUTATION_SHADOWMAPPCF = 1<<14, //< (lightsource) use percentage closer filtering on shadowmap test results
1412 SHADERPERMUTATION_SHADOWSAMPLER = 1<<15, //< (lightsource) use hardware shadowmap test
1413 SHADERPERMUTATION_LIMIT = 1<<16, ///< size of permutations array
1414 SHADERPERMUTATION_COUNT = 16 ///< size of shaderpermutationinfo array
1416 shaderpermutation_t;
1418 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1419 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1421 {"#define USEDIFFUSE\n", " diffuse"},
1422 {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
1423 {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
1424 {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
1425 {"#define USECUBEFILTER\n", " cubefilter"},
1426 {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
1427 {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
1428 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1429 {"#define USEREFLECTION\n", " reflection"},
1430 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1431 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1432 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1433 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1434 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1435 {"#define USESHADOWMAPPCF\n", " shadowmappcf"},
1436 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1439 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1440 typedef enum shadermode_e
1442 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1443 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1444 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1445 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1446 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1447 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1448 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1449 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1450 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1451 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1452 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1453 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1454 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1459 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1460 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1462 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1463 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1464 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1465 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1466 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1467 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1468 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1469 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1470 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1471 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1472 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1473 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1474 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1477 typedef struct r_glsl_permutation_s
1479 /// indicates if we have tried compiling this permutation already
1481 /// 0 if compilation failed
1483 /// locations of detected uniforms in program object, or -1 if not found
1484 int loc_Texture_First;
1485 int loc_Texture_Second;
1486 int loc_Texture_GammaRamps;
1487 int loc_Texture_Normal;
1488 int loc_Texture_Color;
1489 int loc_Texture_Gloss;
1490 int loc_Texture_Glow;
1491 int loc_Texture_SecondaryNormal;
1492 int loc_Texture_SecondaryColor;
1493 int loc_Texture_SecondaryGloss;
1494 int loc_Texture_SecondaryGlow;
1495 int loc_Texture_Pants;
1496 int loc_Texture_Shirt;
1497 int loc_Texture_FogMask;
1498 int loc_Texture_Lightmap;
1499 int loc_Texture_Deluxemap;
1500 int loc_Texture_Attenuation;
1501 int loc_Texture_Cube;
1502 int loc_Texture_Refraction;
1503 int loc_Texture_Reflection;
1504 int loc_Texture_ShadowMapRect;
1505 int loc_Texture_ShadowMapCube;
1506 int loc_Texture_ShadowMap2D;
1507 int loc_Texture_CubeProjection;
1509 int loc_LightPosition;
1510 int loc_EyePosition;
1511 int loc_Color_Pants;
1512 int loc_Color_Shirt;
1513 int loc_FogRangeRecip;
1514 int loc_AmbientScale;
1515 int loc_DiffuseScale;
1516 int loc_SpecularScale;
1517 int loc_SpecularPower;
1519 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1520 int loc_OffsetMapping_Scale;
1522 int loc_AmbientColor;
1523 int loc_DiffuseColor;
1524 int loc_SpecularColor;
1526 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1527 int loc_GammaCoeff; ///< 1 / gamma
1528 int loc_DistortScaleRefractReflect;
1529 int loc_ScreenScaleRefractReflect;
1530 int loc_ScreenCenterRefractReflect;
1531 int loc_RefractColor;
1532 int loc_ReflectColor;
1533 int loc_ReflectFactor;
1534 int loc_ReflectOffset;
1542 int loc_ShadowMap_TextureScale;
1543 int loc_ShadowMap_Parameters;
1545 r_glsl_permutation_t;
1547 /// information about each possible shader permutation
1548 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1549 /// currently selected permutation
1550 r_glsl_permutation_t *r_glsl_permutation;
1552 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1555 if (!filename || !filename[0])
1557 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1560 if (printfromdisknotice)
1561 Con_DPrint("from disk... ");
1562 return shaderstring;
1564 else if (!strcmp(filename, "glsl/default.glsl"))
1566 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1567 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1569 return shaderstring;
1572 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1575 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1576 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1577 int vertstrings_count = 0;
1578 int geomstrings_count = 0;
1579 int fragstrings_count = 0;
1580 char *vertexstring, *geometrystring, *fragmentstring;
1581 const char *vertstrings_list[32+3];
1582 const char *geomstrings_list[32+3];
1583 const char *fragstrings_list[32+3];
1584 char permutationname[256];
1591 permutationname[0] = 0;
1592 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1593 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1594 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1596 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1598 // the first pretext is which type of shader to compile as
1599 // (later these will all be bound together as a program object)
1600 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1601 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1602 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1604 // the second pretext is the mode (for example a light source)
1605 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1606 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1607 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1608 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1610 // now add all the permutation pretexts
1611 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1613 if (permutation & (1<<i))
1615 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1616 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1617 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1618 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1622 // keep line numbers correct
1623 vertstrings_list[vertstrings_count++] = "\n";
1624 geomstrings_list[geomstrings_count++] = "\n";
1625 fragstrings_list[fragstrings_count++] = "\n";
1629 // now append the shader text itself
1630 vertstrings_list[vertstrings_count++] = vertexstring;
1631 geomstrings_list[geomstrings_count++] = geometrystring;
1632 fragstrings_list[fragstrings_count++] = fragmentstring;
1634 // if any sources were NULL, clear the respective list
1636 vertstrings_count = 0;
1637 if (!geometrystring)
1638 geomstrings_count = 0;
1639 if (!fragmentstring)
1640 fragstrings_count = 0;
1642 // compile the shader program
1643 if (vertstrings_count + geomstrings_count + fragstrings_count)
1644 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1648 qglUseProgramObjectARB(p->program);CHECKGLERROR
1649 // look up all the uniform variable names we care about, so we don't
1650 // have to look them up every time we set them
1651 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1652 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1653 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1654 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1655 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1656 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1657 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1658 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1659 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1660 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1661 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1662 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1663 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1664 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1665 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1666 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1667 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1668 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1669 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1670 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1671 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1672 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1673 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1674 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1675 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1676 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1677 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1678 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1679 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1680 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1681 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1682 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1683 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1684 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1685 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1686 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1687 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1688 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1689 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1690 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1691 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1692 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1693 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1694 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1695 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1696 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1697 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1698 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1699 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1700 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1701 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1702 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1703 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1704 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1705 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1706 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1707 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1708 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1709 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1710 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1711 // initialize the samplers to refer to the texture units we use
1712 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1713 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1714 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1715 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1716 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1717 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1718 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1719 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1720 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1721 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1722 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1723 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1724 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1725 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1726 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1727 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1728 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1729 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1730 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1731 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1732 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1733 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1734 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1735 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1737 if (developer.integer)
1738 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1741 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1745 Mem_Free(vertexstring);
1747 Mem_Free(geometrystring);
1749 Mem_Free(fragmentstring);
1752 void R_GLSL_Restart_f(void)
1755 unsigned int permutation;
1756 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1757 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1758 if (r_glsl_permutations[mode][permutation].program)
1759 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1760 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1763 void R_GLSL_DumpShader_f(void)
1767 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1770 Con_Printf("failed to write to glsl/default.glsl\n");
1774 FS_Print(file, "/* The engine may define the following macros:\n");
1775 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1776 for (i = 0;i < SHADERMODE_COUNT;i++)
1777 FS_Print(file, shadermodeinfo[i].pretext);
1778 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1779 FS_Print(file, shaderpermutationinfo[i].pretext);
1780 FS_Print(file, "*/\n");
1781 FS_Print(file, builtinshaderstring);
1784 Con_Printf("glsl/default.glsl written\n");
1787 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1789 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1790 if (r_glsl_permutation != perm)
1792 r_glsl_permutation = perm;
1793 if (!r_glsl_permutation->program)
1795 if (!r_glsl_permutation->compiled)
1796 R_GLSL_CompilePermutation(mode, permutation);
1797 if (!r_glsl_permutation->program)
1799 // remove features until we find a valid permutation
1801 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1803 // reduce i more quickly whenever it would not remove any bits
1804 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1805 if (!(permutation & j))
1808 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1809 if (!r_glsl_permutation->compiled)
1810 R_GLSL_CompilePermutation(mode, permutation);
1811 if (r_glsl_permutation->program)
1814 if (i >= SHADERPERMUTATION_COUNT)
1816 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");
1817 Cvar_SetValueQuick(&r_glsl, 0);
1818 R_GLSL_Restart_f(); // unload shaders
1819 return; // no bit left to clear
1824 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1828 void R_SetupGenericShader(qboolean usetexture)
1830 if (gl_support_fragment_shader)
1832 if (r_glsl.integer && r_glsl_usegeneric.integer)
1833 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1834 else if (r_glsl_permutation)
1836 r_glsl_permutation = NULL;
1837 qglUseProgramObjectARB(0);CHECKGLERROR
1842 void R_SetupGenericTwoTextureShader(int texturemode)
1844 if (gl_support_fragment_shader)
1846 if (r_glsl.integer && r_glsl_usegeneric.integer)
1847 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))));
1848 else if (r_glsl_permutation)
1850 r_glsl_permutation = NULL;
1851 qglUseProgramObjectARB(0);CHECKGLERROR
1854 if (!r_glsl_permutation)
1856 if (texturemode == GL_DECAL && gl_combine.integer)
1857 texturemode = GL_INTERPOLATE_ARB;
1858 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1862 void R_SetupDepthOrShadowShader(void)
1864 if (gl_support_fragment_shader)
1866 if (r_glsl.integer && r_glsl_usegeneric.integer)
1867 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1868 else if (r_glsl_permutation)
1870 r_glsl_permutation = NULL;
1871 qglUseProgramObjectARB(0);CHECKGLERROR
1876 void R_SetupShowDepthShader(void)
1878 if (gl_support_fragment_shader)
1880 if (r_glsl.integer && r_glsl_usegeneric.integer)
1881 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
1882 else if (r_glsl_permutation)
1884 r_glsl_permutation = NULL;
1885 qglUseProgramObjectARB(0);CHECKGLERROR
1890 extern rtexture_t *r_shadow_attenuationgradienttexture;
1891 extern rtexture_t *r_shadow_attenuation2dtexture;
1892 extern rtexture_t *r_shadow_attenuation3dtexture;
1893 extern qboolean r_shadow_usingshadowmaprect;
1894 extern qboolean r_shadow_usingshadowmapcube;
1895 extern qboolean r_shadow_usingshadowmap2d;
1896 extern float r_shadow_shadowmap_texturescale[4];
1897 extern float r_shadow_shadowmap_parameters[4];
1898 extern int r_shadow_shadowmode;
1899 extern int r_shadow_shadowmapfilter;
1900 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1902 // select a permutation of the lighting shader appropriate to this
1903 // combination of texture, entity, light source, and fogging, only use the
1904 // minimum features necessary to avoid wasting rendering time in the
1905 // fragment shader on features that are not being used
1906 unsigned int permutation = 0;
1907 unsigned int mode = 0;
1908 // TODO: implement geometry-shader based shadow volumes someday
1909 if (r_glsl_offsetmapping.integer)
1911 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1912 if (r_glsl_offsetmapping_reliefmapping.integer)
1913 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1915 if (rsurfacepass == RSURFPASS_BACKGROUND)
1917 // distorted background
1918 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1919 mode = SHADERMODE_WATER;
1921 mode = SHADERMODE_REFRACTION;
1923 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1926 mode = SHADERMODE_LIGHTSOURCE;
1927 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1928 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1929 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1930 permutation |= SHADERPERMUTATION_CUBEFILTER;
1931 if (diffusescale > 0)
1932 permutation |= SHADERPERMUTATION_DIFFUSE;
1933 if (specularscale > 0)
1934 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1935 if (r_refdef.fogenabled)
1936 permutation |= SHADERPERMUTATION_FOG;
1937 if (rsurface.texture->colormapping)
1938 permutation |= SHADERPERMUTATION_COLORMAPPING;
1939 if (r_shadow_usingshadowmaprect)
1940 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
1941 if (r_shadow_usingshadowmapcube)
1942 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
1943 if (r_shadow_usingshadowmap2d)
1944 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1945 if (r_shadow_shadowmapfilter == 3)
1946 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
1947 else if (r_shadow_shadowmapfilter == 2)
1948 permutation |= SHADERPERMUTATION_SHADOWMAPPCF | SHADERPERMUTATION_SHADOWSAMPLER;
1949 else if (r_shadow_shadowmapfilter == 1)
1950 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
1952 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1954 // unshaded geometry (fullbright or ambient model lighting)
1955 mode = SHADERMODE_FLATCOLOR;
1956 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1957 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1958 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1959 permutation |= SHADERPERMUTATION_GLOW;
1960 if (r_refdef.fogenabled)
1961 permutation |= SHADERPERMUTATION_FOG;
1962 if (rsurface.texture->colormapping)
1963 permutation |= SHADERPERMUTATION_COLORMAPPING;
1964 if (r_glsl_offsetmapping.integer)
1966 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1967 if (r_glsl_offsetmapping_reliefmapping.integer)
1968 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1970 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1971 permutation |= SHADERPERMUTATION_REFLECTION;
1973 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1975 // directional model lighting
1976 mode = SHADERMODE_LIGHTDIRECTION;
1977 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1978 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1979 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1980 permutation |= SHADERPERMUTATION_GLOW;
1981 permutation |= SHADERPERMUTATION_DIFFUSE;
1982 if (specularscale > 0)
1983 permutation |= SHADERPERMUTATION_SPECULAR;
1984 if (r_refdef.fogenabled)
1985 permutation |= SHADERPERMUTATION_FOG;
1986 if (rsurface.texture->colormapping)
1987 permutation |= SHADERPERMUTATION_COLORMAPPING;
1988 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1989 permutation |= SHADERPERMUTATION_REFLECTION;
1991 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1993 // ambient model lighting
1994 mode = SHADERMODE_LIGHTDIRECTION;
1995 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1996 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1997 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1998 permutation |= SHADERPERMUTATION_GLOW;
1999 if (r_refdef.fogenabled)
2000 permutation |= SHADERPERMUTATION_FOG;
2001 if (rsurface.texture->colormapping)
2002 permutation |= SHADERPERMUTATION_COLORMAPPING;
2003 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2004 permutation |= SHADERPERMUTATION_REFLECTION;
2009 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2011 // deluxemapping (light direction texture)
2012 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2013 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2015 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2016 permutation |= SHADERPERMUTATION_DIFFUSE;
2017 if (specularscale > 0)
2018 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2020 else if (r_glsl_deluxemapping.integer >= 2)
2022 // fake deluxemapping (uniform light direction in tangentspace)
2023 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2024 permutation |= SHADERPERMUTATION_DIFFUSE;
2025 if (specularscale > 0)
2026 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2028 else if (rsurface.uselightmaptexture)
2030 // ordinary lightmapping (q1bsp, q3bsp)
2031 mode = SHADERMODE_LIGHTMAP;
2035 // ordinary vertex coloring (q3bsp)
2036 mode = SHADERMODE_VERTEXCOLOR;
2038 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2039 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2040 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2041 permutation |= SHADERPERMUTATION_GLOW;
2042 if (r_refdef.fogenabled)
2043 permutation |= SHADERPERMUTATION_FOG;
2044 if (rsurface.texture->colormapping)
2045 permutation |= SHADERPERMUTATION_COLORMAPPING;
2046 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2047 permutation |= SHADERPERMUTATION_REFLECTION;
2049 if(permutation & SHADERPERMUTATION_SPECULAR)
2050 if(r_shadow_glossexact.integer)
2051 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2052 R_SetupShader_SetPermutation(mode, permutation);
2053 if (mode == SHADERMODE_LIGHTSOURCE)
2055 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2056 if (permutation & SHADERPERMUTATION_DIFFUSE)
2058 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2059 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2060 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2061 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2065 // ambient only is simpler
2066 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]);
2067 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2068 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2069 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2071 // additive passes are only darkened by fog, not tinted
2072 if (r_glsl_permutation->loc_FogColor >= 0)
2073 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2074 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1], r_shadow_shadowmap_texturescale[2], r_shadow_shadowmap_texturescale[3]);
2075 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]);
2079 if (mode == SHADERMODE_LIGHTDIRECTION)
2081 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);
2082 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);
2083 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);
2084 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]);
2088 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2089 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2090 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2092 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]);
2093 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
2094 // additive passes are only darkened by fog, not tinted
2095 if (r_glsl_permutation->loc_FogColor >= 0)
2097 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2098 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2100 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2102 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);
2103 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]);
2104 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]);
2105 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2106 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2107 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2108 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2110 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2111 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
2112 if (r_glsl_permutation->loc_Color_Pants >= 0)
2114 if (rsurface.texture->currentskinframe->pants)
2115 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2117 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2119 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2121 if (rsurface.texture->currentskinframe->shirt)
2122 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2124 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2126 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
2127 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2129 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2133 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2135 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2139 #define SKINFRAME_HASH 1024
2143 int loadsequence; // incremented each level change
2144 memexpandablearray_t array;
2145 skinframe_t *hash[SKINFRAME_HASH];
2148 r_skinframe_t r_skinframe;
2150 void R_SkinFrame_PrepareForPurge(void)
2152 r_skinframe.loadsequence++;
2153 // wrap it without hitting zero
2154 if (r_skinframe.loadsequence >= 200)
2155 r_skinframe.loadsequence = 1;
2158 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2162 // mark the skinframe as used for the purging code
2163 skinframe->loadsequence = r_skinframe.loadsequence;
2166 void R_SkinFrame_Purge(void)
2170 for (i = 0;i < SKINFRAME_HASH;i++)
2172 for (s = r_skinframe.hash[i];s;s = s->next)
2174 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2176 if (s->merged == s->base)
2178 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2179 R_PurgeTexture(s->stain );s->stain = NULL;
2180 R_PurgeTexture(s->merged);s->merged = NULL;
2181 R_PurgeTexture(s->base );s->base = NULL;
2182 R_PurgeTexture(s->pants );s->pants = NULL;
2183 R_PurgeTexture(s->shirt );s->shirt = NULL;
2184 R_PurgeTexture(s->nmap );s->nmap = NULL;
2185 R_PurgeTexture(s->gloss );s->gloss = NULL;
2186 R_PurgeTexture(s->glow );s->glow = NULL;
2187 R_PurgeTexture(s->fog );s->fog = NULL;
2188 s->loadsequence = 0;
2194 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2196 char basename[MAX_QPATH];
2198 Image_StripImageExtension(name, basename, sizeof(basename));
2200 if( last == NULL ) {
2202 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2203 item = r_skinframe.hash[hashindex];
2208 // linearly search through the hash bucket
2209 for( ; item ; item = item->next ) {
2210 if( !strcmp( item->basename, basename ) ) {
2217 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2221 char basename[MAX_QPATH];
2223 Image_StripImageExtension(name, basename, sizeof(basename));
2225 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2226 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2227 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2231 rtexture_t *dyntexture;
2232 // check whether its a dynamic texture
2233 dyntexture = CL_GetDynTexture( basename );
2234 if (!add && !dyntexture)
2236 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2237 memset(item, 0, sizeof(*item));
2238 strlcpy(item->basename, basename, sizeof(item->basename));
2239 item->base = dyntexture; // either NULL or dyntexture handle
2240 item->textureflags = textureflags;
2241 item->comparewidth = comparewidth;
2242 item->compareheight = compareheight;
2243 item->comparecrc = comparecrc;
2244 item->next = r_skinframe.hash[hashindex];
2245 r_skinframe.hash[hashindex] = item;
2247 else if( item->base == NULL )
2249 rtexture_t *dyntexture;
2250 // check whether its a dynamic texture
2251 // 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]
2252 dyntexture = CL_GetDynTexture( basename );
2253 item->base = dyntexture; // either NULL or dyntexture handle
2256 R_SkinFrame_MarkUsed(item);
2260 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2262 unsigned long long avgcolor[5], wsum; \
2270 for(pix = 0; pix < cnt; ++pix) \
2273 for(comp = 0; comp < 3; ++comp) \
2275 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2278 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2280 for(comp = 0; comp < 3; ++comp) \
2281 avgcolor[comp] += getpixel * w; \
2284 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2285 avgcolor[4] += getpixel; \
2287 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2289 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2290 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2291 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2292 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2295 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2297 // FIXME: it should be possible to disable loading various layers using
2298 // cvars, to prevent wasted loading time and memory usage if the user does
2300 qboolean loadnormalmap = true;
2301 qboolean loadgloss = true;
2302 qboolean loadpantsandshirt = true;
2303 qboolean loadglow = true;
2305 unsigned char *pixels;
2306 unsigned char *bumppixels;
2307 unsigned char *basepixels = NULL;
2308 int basepixels_width;
2309 int basepixels_height;
2310 skinframe_t *skinframe;
2314 if (cls.state == ca_dedicated)
2317 // return an existing skinframe if already loaded
2318 // if loading of the first image fails, don't make a new skinframe as it
2319 // would cause all future lookups of this to be missing
2320 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2321 if (skinframe && skinframe->base)
2324 basepixels = loadimagepixelsbgra(name, complain, true);
2325 if (basepixels == NULL)
2328 if (developer_loading.integer)
2329 Con_Printf("loading skin \"%s\"\n", name);
2331 // we've got some pixels to store, so really allocate this new texture now
2333 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2334 skinframe->stain = NULL;
2335 skinframe->merged = NULL;
2336 skinframe->base = r_texture_notexture;
2337 skinframe->pants = NULL;
2338 skinframe->shirt = NULL;
2339 skinframe->nmap = r_texture_blanknormalmap;
2340 skinframe->gloss = NULL;
2341 skinframe->glow = NULL;
2342 skinframe->fog = NULL;
2344 basepixels_width = image_width;
2345 basepixels_height = image_height;
2346 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);
2348 if (textureflags & TEXF_ALPHA)
2350 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2351 if (basepixels[j] < 255)
2353 if (j < basepixels_width * basepixels_height * 4)
2355 // has transparent pixels
2357 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2358 for (j = 0;j < image_width * image_height * 4;j += 4)
2363 pixels[j+3] = basepixels[j+3];
2365 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);
2370 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2371 //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]);
2373 // _norm is the name used by tenebrae and has been adopted as standard
2376 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2378 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);
2382 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2384 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2385 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2386 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);
2388 Mem_Free(bumppixels);
2390 else if (r_shadow_bumpscale_basetexture.value > 0)
2392 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2393 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2394 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);
2398 // _luma is supported for tenebrae compatibility
2399 // (I think it's a very stupid name, but oh well)
2400 // _glow is the preferred name
2401 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;}
2402 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;}
2403 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;}
2404 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;}
2407 Mem_Free(basepixels);
2412 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2415 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2418 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)
2423 for (i = 0;i < width*height;i++)
2424 if (((unsigned char *)&palette[in[i]])[3] > 0)
2426 if (i == width*height)
2429 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2432 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2433 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2436 unsigned char *temp1, *temp2;
2437 skinframe_t *skinframe;
2439 if (cls.state == ca_dedicated)
2442 // if already loaded just return it, otherwise make a new skinframe
2443 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2444 if (skinframe && skinframe->base)
2447 skinframe->stain = NULL;
2448 skinframe->merged = NULL;
2449 skinframe->base = r_texture_notexture;
2450 skinframe->pants = NULL;
2451 skinframe->shirt = NULL;
2452 skinframe->nmap = r_texture_blanknormalmap;
2453 skinframe->gloss = NULL;
2454 skinframe->glow = NULL;
2455 skinframe->fog = NULL;
2457 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2461 if (developer_loading.integer)
2462 Con_Printf("loading 32bit skin \"%s\"\n", name);
2464 if (r_shadow_bumpscale_basetexture.value > 0)
2466 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2467 temp2 = temp1 + width * height * 4;
2468 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2469 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2472 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2473 if (textureflags & TEXF_ALPHA)
2475 for (i = 3;i < width * height * 4;i += 4)
2476 if (skindata[i] < 255)
2478 if (i < width * height * 4)
2480 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2481 memcpy(fogpixels, skindata, width * height * 4);
2482 for (i = 0;i < width * height * 4;i += 4)
2483 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2484 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2485 Mem_Free(fogpixels);
2489 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2490 //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]);
2495 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2498 unsigned char *temp1, *temp2;
2499 unsigned int *palette;
2500 skinframe_t *skinframe;
2502 if (cls.state == ca_dedicated)
2505 // if already loaded just return it, otherwise make a new skinframe
2506 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2507 if (skinframe && skinframe->base)
2510 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2512 skinframe->stain = NULL;
2513 skinframe->merged = NULL;
2514 skinframe->base = r_texture_notexture;
2515 skinframe->pants = NULL;
2516 skinframe->shirt = NULL;
2517 skinframe->nmap = r_texture_blanknormalmap;
2518 skinframe->gloss = NULL;
2519 skinframe->glow = NULL;
2520 skinframe->fog = NULL;
2522 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2526 if (developer_loading.integer)
2527 Con_Printf("loading quake skin \"%s\"\n", name);
2529 if (r_shadow_bumpscale_basetexture.value > 0)
2531 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2532 temp2 = temp1 + width * height * 4;
2533 // use either a custom palette or the quake palette
2534 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2535 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2536 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2539 // use either a custom palette, or the quake palette
2540 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2541 if (loadglowtexture)
2542 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2543 if (loadpantsandshirt)
2545 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2546 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2548 if (skinframe->pants || skinframe->shirt)
2549 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
2550 if (textureflags & TEXF_ALPHA)
2552 for (i = 0;i < width * height;i++)
2553 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2555 if (i < width * height)
2556 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2559 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2560 //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]);
2565 skinframe_t *R_SkinFrame_LoadMissing(void)
2567 skinframe_t *skinframe;
2569 if (cls.state == ca_dedicated)
2572 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2573 skinframe->stain = NULL;
2574 skinframe->merged = NULL;
2575 skinframe->base = r_texture_notexture;
2576 skinframe->pants = NULL;
2577 skinframe->shirt = NULL;
2578 skinframe->nmap = r_texture_blanknormalmap;
2579 skinframe->gloss = NULL;
2580 skinframe->glow = NULL;
2581 skinframe->fog = NULL;
2583 skinframe->avgcolor[0] = rand() / RAND_MAX;
2584 skinframe->avgcolor[1] = rand() / RAND_MAX;
2585 skinframe->avgcolor[2] = rand() / RAND_MAX;
2586 skinframe->avgcolor[3] = 1;
2591 void gl_main_start(void)
2595 memset(r_queries, 0, sizeof(r_queries));
2597 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2598 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2600 // set up r_skinframe loading system for textures
2601 memset(&r_skinframe, 0, sizeof(r_skinframe));
2602 r_skinframe.loadsequence = 1;
2603 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2605 r_main_texturepool = R_AllocTexturePool();
2606 R_BuildBlankTextures();
2608 if (gl_texturecubemap)
2611 R_BuildNormalizationCube();
2613 r_texture_fogattenuation = NULL;
2614 r_texture_gammaramps = NULL;
2615 //r_texture_fogintensity = NULL;
2616 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2617 memset(&r_waterstate, 0, sizeof(r_waterstate));
2618 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2619 memset(&r_svbsp, 0, sizeof (r_svbsp));
2621 r_refdef.fogmasktable_density = 0;
2624 extern rtexture_t *loadingscreentexture;
2625 void gl_main_shutdown(void)
2628 qglDeleteQueriesARB(r_maxqueries, r_queries);
2632 memset(r_queries, 0, sizeof(r_queries));
2634 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2635 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2637 // clear out the r_skinframe state
2638 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2639 memset(&r_skinframe, 0, sizeof(r_skinframe));
2642 Mem_Free(r_svbsp.nodes);
2643 memset(&r_svbsp, 0, sizeof (r_svbsp));
2644 R_FreeTexturePool(&r_main_texturepool);
2645 loadingscreentexture = NULL;
2646 r_texture_blanknormalmap = NULL;
2647 r_texture_white = NULL;
2648 r_texture_grey128 = NULL;
2649 r_texture_black = NULL;
2650 r_texture_whitecube = NULL;
2651 r_texture_normalizationcube = NULL;
2652 r_texture_fogattenuation = NULL;
2653 r_texture_gammaramps = NULL;
2654 //r_texture_fogintensity = NULL;
2655 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2656 memset(&r_waterstate, 0, sizeof(r_waterstate));
2660 extern void CL_ParseEntityLump(char *entitystring);
2661 void gl_main_newmap(void)
2663 // FIXME: move this code to client
2665 char *entities, entname[MAX_QPATH];
2668 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2669 l = (int)strlen(entname) - 4;
2670 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2672 memcpy(entname + l, ".ent", 5);
2673 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2675 CL_ParseEntityLump(entities);
2680 if (cl.worldmodel->brush.entities)
2681 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2685 void GL_Main_Init(void)
2687 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2689 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2690 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2691 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2692 if (gamemode == GAME_NEHAHRA)
2694 Cvar_RegisterVariable (&gl_fogenable);
2695 Cvar_RegisterVariable (&gl_fogdensity);
2696 Cvar_RegisterVariable (&gl_fogred);
2697 Cvar_RegisterVariable (&gl_foggreen);
2698 Cvar_RegisterVariable (&gl_fogblue);
2699 Cvar_RegisterVariable (&gl_fogstart);
2700 Cvar_RegisterVariable (&gl_fogend);
2701 Cvar_RegisterVariable (&gl_skyclip);
2703 Cvar_RegisterVariable(&r_motionblur);
2704 Cvar_RegisterVariable(&r_motionblur_maxblur);
2705 Cvar_RegisterVariable(&r_motionblur_bmin);
2706 Cvar_RegisterVariable(&r_motionblur_vmin);
2707 Cvar_RegisterVariable(&r_motionblur_vmax);
2708 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2709 Cvar_RegisterVariable(&r_motionblur_randomize);
2710 Cvar_RegisterVariable(&r_damageblur);
2711 Cvar_RegisterVariable(&r_animcache);
2712 Cvar_RegisterVariable(&r_depthfirst);
2713 Cvar_RegisterVariable(&r_useinfinitefarclip);
2714 Cvar_RegisterVariable(&r_nearclip);
2715 Cvar_RegisterVariable(&r_showbboxes);
2716 Cvar_RegisterVariable(&r_showsurfaces);
2717 Cvar_RegisterVariable(&r_showtris);
2718 Cvar_RegisterVariable(&r_shownormals);
2719 Cvar_RegisterVariable(&r_showlighting);
2720 Cvar_RegisterVariable(&r_showshadowvolumes);
2721 Cvar_RegisterVariable(&r_showcollisionbrushes);
2722 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2723 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2724 Cvar_RegisterVariable(&r_showdisabledepthtest);
2725 Cvar_RegisterVariable(&r_drawportals);
2726 Cvar_RegisterVariable(&r_drawentities);
2727 Cvar_RegisterVariable(&r_cullentities_trace);
2728 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2729 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2730 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2731 Cvar_RegisterVariable(&r_drawviewmodel);
2732 Cvar_RegisterVariable(&r_speeds);
2733 Cvar_RegisterVariable(&r_fullbrights);
2734 Cvar_RegisterVariable(&r_wateralpha);
2735 Cvar_RegisterVariable(&r_dynamic);
2736 Cvar_RegisterVariable(&r_fullbright);
2737 Cvar_RegisterVariable(&r_shadows);
2738 Cvar_RegisterVariable(&r_shadows_darken);
2739 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
2740 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2741 Cvar_RegisterVariable(&r_shadows_throwdistance);
2742 Cvar_RegisterVariable(&r_shadows_throwdirection);
2743 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2744 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2745 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2746 Cvar_RegisterVariable(&r_fog_exp2);
2747 Cvar_RegisterVariable(&r_drawfog);
2748 Cvar_RegisterVariable(&r_textureunits);
2749 Cvar_RegisterVariable(&r_glsl);
2750 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2751 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2752 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2753 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2754 Cvar_RegisterVariable(&r_glsl_postprocess);
2755 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2756 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2757 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2758 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2759 Cvar_RegisterVariable(&r_glsl_usegeneric);
2760 Cvar_RegisterVariable(&r_water);
2761 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2762 Cvar_RegisterVariable(&r_water_clippingplanebias);
2763 Cvar_RegisterVariable(&r_water_refractdistort);
2764 Cvar_RegisterVariable(&r_water_reflectdistort);
2765 Cvar_RegisterVariable(&r_lerpsprites);
2766 Cvar_RegisterVariable(&r_lerpmodels);
2767 Cvar_RegisterVariable(&r_lerplightstyles);
2768 Cvar_RegisterVariable(&r_waterscroll);
2769 Cvar_RegisterVariable(&r_bloom);
2770 Cvar_RegisterVariable(&r_bloom_colorscale);
2771 Cvar_RegisterVariable(&r_bloom_brighten);
2772 Cvar_RegisterVariable(&r_bloom_blur);
2773 Cvar_RegisterVariable(&r_bloom_resolution);
2774 Cvar_RegisterVariable(&r_bloom_colorexponent);
2775 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2776 Cvar_RegisterVariable(&r_hdr);
2777 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2778 Cvar_RegisterVariable(&r_hdr_glowintensity);
2779 Cvar_RegisterVariable(&r_hdr_range);
2780 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2781 Cvar_RegisterVariable(&developer_texturelogging);
2782 Cvar_RegisterVariable(&gl_lightmaps);
2783 Cvar_RegisterVariable(&r_test);
2784 Cvar_RegisterVariable(&r_batchmode);
2785 Cvar_RegisterVariable(&r_glsl_saturation);
2786 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2787 Cvar_SetValue("r_fullbrights", 0);
2788 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2790 Cvar_RegisterVariable(&r_track_sprites);
2791 Cvar_RegisterVariable(&r_track_sprites_flags);
2792 Cvar_RegisterVariable(&r_track_sprites_scalew);
2793 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2796 extern void R_Textures_Init(void);
2797 extern void GL_Draw_Init(void);
2798 extern void GL_Main_Init(void);
2799 extern void R_Shadow_Init(void);
2800 extern void R_Sky_Init(void);
2801 extern void GL_Surf_Init(void);
2802 extern void R_Particles_Init(void);
2803 extern void R_Explosion_Init(void);
2804 extern void gl_backend_init(void);
2805 extern void Sbar_Init(void);
2806 extern void R_LightningBeams_Init(void);
2807 extern void Mod_RenderInit(void);
2809 void Render_Init(void)
2821 R_LightningBeams_Init();
2830 extern char *ENGINE_EXTENSIONS;
2833 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2834 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2835 gl_version = (const char *)qglGetString(GL_VERSION);
2836 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2840 if (!gl_platformextensions)
2841 gl_platformextensions = "";
2843 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2844 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2845 Con_Printf("GL_VERSION: %s\n", gl_version);
2846 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2847 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2849 VID_CheckExtensions();
2851 // LordHavoc: report supported extensions
2852 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2854 // clear to black (loading plaque will be seen over this)
2856 qglClearColor(0,0,0,1);CHECKGLERROR
2857 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2860 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2864 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2866 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2869 p = r_refdef.view.frustum + i;
2874 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2878 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2882 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2886 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2890 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2894 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2898 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2902 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2910 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2914 for (i = 0;i < numplanes;i++)
2921 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2925 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2929 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2933 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2937 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2941 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2945 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2949 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2957 //==================================================================================
2959 // LordHavoc: animcache written by Echon, refactored and reformatted by me
2962 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
2963 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
2964 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
2967 typedef struct r_animcache_entity_s
2974 qboolean wantnormals;
2975 qboolean wanttangents;
2977 r_animcache_entity_t;
2979 typedef struct r_animcache_s
2981 r_animcache_entity_t entity[MAX_EDICTS*2];
2987 static r_animcache_t r_animcachestate;
2989 void R_AnimCache_Free(void)
2992 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
2994 r_animcachestate.entity[idx].maxvertices = 0;
2995 Mem_Free(r_animcachestate.entity[idx].vertex3f);
2996 r_animcachestate.entity[idx].vertex3f = NULL;
2997 r_animcachestate.entity[idx].normal3f = NULL;
2998 r_animcachestate.entity[idx].svector3f = NULL;
2999 r_animcachestate.entity[idx].tvector3f = NULL;
3001 r_animcachestate.currentindex = 0;
3002 r_animcachestate.maxindex = 0;
3005 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3009 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3011 if (cache->maxvertices >= numvertices)
3014 // Release existing memory
3015 if (cache->vertex3f)
3016 Mem_Free(cache->vertex3f);
3018 // Pad by 1024 verts
3019 cache->maxvertices = (numvertices + 1023) & ~1023;
3020 arraySize = cache->maxvertices * 3;
3022 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3023 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3024 r_animcachestate.entity[cacheIdx].vertex3f = base;
3025 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3026 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3027 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3029 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3032 void R_AnimCache_NewFrame(void)
3036 if (r_animcache.integer && r_drawentities.integer)
3037 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3038 else if (r_animcachestate.maxindex)
3041 r_animcachestate.currentindex = 0;
3043 for (i = 0;i < r_refdef.scene.numentities;i++)
3044 r_refdef.scene.entities[i]->animcacheindex = -1;
3047 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3049 dp_model_t *model = ent->model;
3050 r_animcache_entity_t *c;
3051 // see if it's already cached this frame
3052 if (ent->animcacheindex >= 0)
3054 // add normals/tangents if needed
3055 c = r_animcachestate.entity + ent->animcacheindex;
3057 wantnormals = false;
3058 if (c->wanttangents)
3059 wanttangents = false;
3060 if (wantnormals || wanttangents)
3061 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3065 // see if this ent is worth caching
3066 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3068 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3070 // assign it a cache entry and make sure the arrays are big enough
3071 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3072 ent->animcacheindex = r_animcachestate.currentindex++;
3073 c = r_animcachestate.entity + ent->animcacheindex;
3074 c->wantnormals = wantnormals;
3075 c->wanttangents = wanttangents;
3076 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3081 void R_AnimCache_CacheVisibleEntities(void)
3084 qboolean wantnormals;
3085 qboolean wanttangents;
3087 if (!r_animcachestate.maxindex)
3090 wantnormals = !r_showsurfaces.integer;
3091 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3093 // TODO: thread this?
3095 for (i = 0;i < r_refdef.scene.numentities;i++)
3097 if (!r_refdef.viewcache.entityvisible[i])
3099 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3103 //==================================================================================
3105 static void R_View_UpdateEntityLighting (void)
3108 entity_render_t *ent;
3109 vec3_t tempdiffusenormal;
3111 for (i = 0;i < r_refdef.scene.numentities;i++)
3113 ent = r_refdef.scene.entities[i];
3115 // skip unseen models
3116 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3120 if (ent->model && ent->model->brush.num_leafs)
3122 // TODO: use modellight for r_ambient settings on world?
3123 VectorSet(ent->modellight_ambient, 0, 0, 0);
3124 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3125 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3129 // fetch the lighting from the worldmodel data
3130 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));
3131 VectorClear(ent->modellight_diffuse);
3132 VectorClear(tempdiffusenormal);
3133 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3136 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3137 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3140 VectorSet(ent->modellight_ambient, 1, 1, 1);
3142 // move the light direction into modelspace coordinates for lighting code
3143 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3144 if(VectorLength2(ent->modellight_lightdir) == 0)
3145 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3146 VectorNormalize(ent->modellight_lightdir);
3150 static void R_View_UpdateEntityVisible (void)
3153 entity_render_t *ent;
3155 if (!r_drawentities.integer)
3158 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3159 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3161 // worldmodel can check visibility
3162 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3163 for (i = 0;i < r_refdef.scene.numentities;i++)
3165 ent = r_refdef.scene.entities[i];
3166 if (!(ent->flags & renderimask))
3167 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)))
3168 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))
3169 r_refdef.viewcache.entityvisible[i] = true;
3171 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3173 for (i = 0;i < r_refdef.scene.numentities;i++)
3175 ent = r_refdef.scene.entities[i];
3176 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
3178 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))
3179 ent->last_trace_visibility = realtime;
3180 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3181 r_refdef.viewcache.entityvisible[i] = 0;
3188 // no worldmodel or it can't check visibility
3189 for (i = 0;i < r_refdef.scene.numentities;i++)
3191 ent = r_refdef.scene.entities[i];
3192 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));
3197 /// only used if skyrendermasked, and normally returns false
3198 int R_DrawBrushModelsSky (void)
3201 entity_render_t *ent;
3203 if (!r_drawentities.integer)
3207 for (i = 0;i < r_refdef.scene.numentities;i++)
3209 if (!r_refdef.viewcache.entityvisible[i])
3211 ent = r_refdef.scene.entities[i];
3212 if (!ent->model || !ent->model->DrawSky)
3214 ent->model->DrawSky(ent);
3220 static void R_DrawNoModel(entity_render_t *ent);
3221 static void R_DrawModels(void)
3224 entity_render_t *ent;
3226 if (!r_drawentities.integer)
3229 for (i = 0;i < r_refdef.scene.numentities;i++)
3231 if (!r_refdef.viewcache.entityvisible[i])
3233 ent = r_refdef.scene.entities[i];
3234 r_refdef.stats.entities++;
3235 if (ent->model && ent->model->Draw != NULL)
3236 ent->model->Draw(ent);
3242 static void R_DrawModelsDepth(void)
3245 entity_render_t *ent;
3247 if (!r_drawentities.integer)
3250 for (i = 0;i < r_refdef.scene.numentities;i++)
3252 if (!r_refdef.viewcache.entityvisible[i])
3254 ent = r_refdef.scene.entities[i];
3255 if (ent->model && ent->model->DrawDepth != NULL)
3256 ent->model->DrawDepth(ent);
3260 static void R_DrawModelsDebug(void)
3263 entity_render_t *ent;
3265 if (!r_drawentities.integer)
3268 for (i = 0;i < r_refdef.scene.numentities;i++)
3270 if (!r_refdef.viewcache.entityvisible[i])
3272 ent = r_refdef.scene.entities[i];
3273 if (ent->model && ent->model->DrawDebug != NULL)
3274 ent->model->DrawDebug(ent);
3278 static void R_DrawModelsAddWaterPlanes(void)
3281 entity_render_t *ent;
3283 if (!r_drawentities.integer)
3286 for (i = 0;i < r_refdef.scene.numentities;i++)
3288 if (!r_refdef.viewcache.entityvisible[i])
3290 ent = r_refdef.scene.entities[i];
3291 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3292 ent->model->DrawAddWaterPlanes(ent);
3296 static void R_View_SetFrustum(void)
3299 double slopex, slopey;
3300 vec3_t forward, left, up, origin;
3302 // we can't trust r_refdef.view.forward and friends in reflected scenes
3303 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3306 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3307 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3308 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3309 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3310 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3311 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3312 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3313 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3314 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3315 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3316 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3317 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3321 zNear = r_refdef.nearclip;
3322 nudge = 1.0 - 1.0 / (1<<23);
3323 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3324 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3325 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3326 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3327 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3328 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3329 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3330 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3336 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3337 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3338 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3339 r_refdef.view.frustum[0].dist = m[15] - m[12];
3341 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3342 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3343 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3344 r_refdef.view.frustum[1].dist = m[15] + m[12];
3346 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3347 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3348 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3349 r_refdef.view.frustum[2].dist = m[15] - m[13];
3351 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3352 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3353 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3354 r_refdef.view.frustum[3].dist = m[15] + m[13];
3356 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3357 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3358 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3359 r_refdef.view.frustum[4].dist = m[15] - m[14];
3361 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3362 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3363 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3364 r_refdef.view.frustum[5].dist = m[15] + m[14];
3367 if (r_refdef.view.useperspective)
3369 slopex = 1.0 / r_refdef.view.frustum_x;
3370 slopey = 1.0 / r_refdef.view.frustum_y;
3371 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3372 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3373 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3374 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3375 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3377 // Leaving those out was a mistake, those were in the old code, and they
3378 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3379 // I couldn't reproduce it after adding those normalizations. --blub
3380 VectorNormalize(r_refdef.view.frustum[0].normal);
3381 VectorNormalize(r_refdef.view.frustum[1].normal);
3382 VectorNormalize(r_refdef.view.frustum[2].normal);
3383 VectorNormalize(r_refdef.view.frustum[3].normal);
3385 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3386 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]);
3387 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]);
3388 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]);
3389 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]);
3391 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3392 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3393 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3394 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3395 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3399 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3400 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3401 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3402 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3403 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3404 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3405 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3406 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3407 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3408 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3410 r_refdef.view.numfrustumplanes = 5;
3412 if (r_refdef.view.useclipplane)
3414 r_refdef.view.numfrustumplanes = 6;
3415 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3418 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3419 PlaneClassify(r_refdef.view.frustum + i);
3421 // LordHavoc: note to all quake engine coders, Quake had a special case
3422 // for 90 degrees which assumed a square view (wrong), so I removed it,
3423 // Quake2 has it disabled as well.
3425 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3426 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3427 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3428 //PlaneClassify(&frustum[0]);
3430 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3431 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3432 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3433 //PlaneClassify(&frustum[1]);
3435 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3436 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3437 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3438 //PlaneClassify(&frustum[2]);
3440 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3441 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3442 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3443 //PlaneClassify(&frustum[3]);
3446 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3447 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3448 //PlaneClassify(&frustum[4]);
3451 void R_View_Update(void)
3453 R_View_SetFrustum();
3454 R_View_WorldVisibility(r_refdef.view.useclipplane);
3455 R_View_UpdateEntityVisible();
3456 R_View_UpdateEntityLighting();
3459 void R_SetupView(qboolean allowwaterclippingplane)
3461 const double *customclipplane = NULL;
3463 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3465 // LordHavoc: couldn't figure out how to make this approach the
3466 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3467 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3468 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3469 dist = r_refdef.view.clipplane.dist;
3470 plane[0] = r_refdef.view.clipplane.normal[0];
3471 plane[1] = r_refdef.view.clipplane.normal[1];
3472 plane[2] = r_refdef.view.clipplane.normal[2];
3474 customclipplane = plane;
3477 if (!r_refdef.view.useperspective)
3478 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);
3479 else if (gl_stencil && r_useinfinitefarclip.integer)
3480 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);
3482 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);
3483 R_SetViewport(&r_refdef.view.viewport);
3486 void R_ResetViewRendering2D(void)
3488 r_viewport_t viewport;
3491 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3492 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);
3493 R_SetViewport(&viewport);
3494 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3495 GL_Color(1, 1, 1, 1);
3496 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3497 GL_BlendFunc(GL_ONE, GL_ZERO);
3498 GL_AlphaTest(false);
3499 GL_ScissorTest(false);
3500 GL_DepthMask(false);
3501 GL_DepthRange(0, 1);
3502 GL_DepthTest(false);
3503 R_Mesh_Matrix(&identitymatrix);
3504 R_Mesh_ResetTextureState();
3505 GL_PolygonOffset(0, 0);
3506 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3507 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3508 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3509 qglStencilMask(~0);CHECKGLERROR
3510 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3511 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3512 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3513 R_SetupGenericShader(true);
3516 void R_ResetViewRendering3D(void)
3521 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3522 GL_Color(1, 1, 1, 1);
3523 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3524 GL_BlendFunc(GL_ONE, GL_ZERO);
3525 GL_AlphaTest(false);
3526 GL_ScissorTest(true);
3528 GL_DepthRange(0, 1);
3530 R_Mesh_Matrix(&identitymatrix);
3531 R_Mesh_ResetTextureState();
3532 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3533 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3534 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3535 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3536 qglStencilMask(~0);CHECKGLERROR
3537 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3538 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3539 GL_CullFace(r_refdef.view.cullface_back);
3540 R_SetupGenericShader(true);
3543 void R_RenderScene(void);
3544 void R_RenderWaterPlanes(void);
3546 static void R_Water_StartFrame(void)
3549 int waterwidth, waterheight, texturewidth, textureheight;
3550 r_waterstate_waterplane_t *p;
3552 // set waterwidth and waterheight to the water resolution that will be
3553 // used (often less than the screen resolution for faster rendering)
3554 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3555 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3557 // calculate desired texture sizes
3558 // can't use water if the card does not support the texture size
3559 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3560 texturewidth = textureheight = waterwidth = waterheight = 0;
3561 else if (gl_support_arb_texture_non_power_of_two)
3563 texturewidth = waterwidth;
3564 textureheight = waterheight;
3568 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3569 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3572 // allocate textures as needed
3573 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3575 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3576 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3578 if (p->texture_refraction)
3579 R_FreeTexture(p->texture_refraction);
3580 p->texture_refraction = NULL;
3581 if (p->texture_reflection)
3582 R_FreeTexture(p->texture_reflection);
3583 p->texture_reflection = NULL;
3585 memset(&r_waterstate, 0, sizeof(r_waterstate));
3586 r_waterstate.waterwidth = waterwidth;
3587 r_waterstate.waterheight = waterheight;
3588 r_waterstate.texturewidth = texturewidth;
3589 r_waterstate.textureheight = textureheight;
3592 // when doing a reduced render (HDR) we want to use a smaller area
3593 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3594 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3596 if (r_waterstate.waterwidth)
3598 r_waterstate.enabled = true;
3600 // set up variables that will be used in shader setup
3601 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3602 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3603 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3604 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3607 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3608 r_waterstate.numwaterplanes = 0;
3611 void R_Water_AddWaterPlane(msurface_t *surface)
3613 int triangleindex, planeindex;
3619 r_waterstate_waterplane_t *p;
3620 texture_t *t = R_GetCurrentTexture(surface->texture);
3621 // just use the first triangle with a valid normal for any decisions
3622 VectorClear(normal);
3623 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3625 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3626 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3627 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3628 TriangleNormal(vert[0], vert[1], vert[2], normal);
3629 if (VectorLength2(normal) >= 0.001)
3633 VectorCopy(normal, plane.normal);
3634 VectorNormalize(plane.normal);
3635 plane.dist = DotProduct(vert[0], plane.normal);
3636 PlaneClassify(&plane);
3637 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3639 // skip backfaces (except if nocullface is set)
3640 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3642 VectorNegate(plane.normal, plane.normal);
3644 PlaneClassify(&plane);
3648 // find a matching plane if there is one
3649 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3650 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3652 if (planeindex >= r_waterstate.maxwaterplanes)
3653 return; // nothing we can do, out of planes
3655 // if this triangle does not fit any known plane rendered this frame, add one
3656 if (planeindex >= r_waterstate.numwaterplanes)
3658 // store the new plane
3659 r_waterstate.numwaterplanes++;
3661 // clear materialflags and pvs
3662 p->materialflags = 0;
3663 p->pvsvalid = false;
3665 // merge this surface's materialflags into the waterplane
3666 p->materialflags |= t->currentmaterialflags;
3667 // merge this surface's PVS into the waterplane
3668 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3669 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3670 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3672 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3677 static void R_Water_ProcessPlanes(void)
3679 r_refdef_view_t originalview;
3680 r_refdef_view_t myview;
3682 r_waterstate_waterplane_t *p;
3684 originalview = r_refdef.view;
3686 // make sure enough textures are allocated
3687 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3689 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3691 if (!p->texture_refraction)
3692 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);
3693 if (!p->texture_refraction)
3697 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3699 if (!p->texture_reflection)
3700 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);
3701 if (!p->texture_reflection)
3707 r_refdef.view = originalview;
3708 r_refdef.view.showdebug = false;
3709 r_refdef.view.width = r_waterstate.waterwidth;
3710 r_refdef.view.height = r_waterstate.waterheight;
3711 r_refdef.view.useclipplane = true;
3712 myview = r_refdef.view;
3713 r_waterstate.renderingscene = true;
3714 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3716 // render the normal view scene and copy into texture
3717 // (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)
3718 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3720 r_refdef.view = myview;
3721 r_refdef.view.clipplane = p->plane;
3722 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3723 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3724 PlaneClassify(&r_refdef.view.clipplane);
3726 R_ResetViewRendering3D();
3727 R_ClearScreen(r_refdef.fogenabled);
3731 // copy view into the screen texture
3732 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3733 GL_ActiveTexture(0);
3735 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
3738 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3740 r_refdef.view = myview;
3741 // render reflected scene and copy into texture
3742 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3743 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3744 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3745 r_refdef.view.clipplane = p->plane;
3746 // reverse the cullface settings for this render
3747 r_refdef.view.cullface_front = GL_FRONT;
3748 r_refdef.view.cullface_back = GL_BACK;
3749 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3751 r_refdef.view.usecustompvs = true;
3753 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3755 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3758 R_ResetViewRendering3D();
3759 R_ClearScreen(r_refdef.fogenabled);
3763 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3764 GL_ActiveTexture(0);
3766 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
3769 r_waterstate.renderingscene = false;
3770 r_refdef.view = originalview;
3771 R_ResetViewRendering3D();
3772 R_ClearScreen(r_refdef.fogenabled);
3776 r_refdef.view = originalview;
3777 r_waterstate.renderingscene = false;
3778 Cvar_SetValueQuick(&r_water, 0);
3779 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3783 void R_Bloom_StartFrame(void)
3785 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3787 // set bloomwidth and bloomheight to the bloom resolution that will be
3788 // used (often less than the screen resolution for faster rendering)
3789 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
3790 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
3791 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
3792 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
3793 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
3795 // calculate desired texture sizes
3796 if (gl_support_arb_texture_non_power_of_two)
3798 screentexturewidth = r_refdef.view.width;
3799 screentextureheight = r_refdef.view.height;
3800 bloomtexturewidth = r_bloomstate.bloomwidth;
3801 bloomtextureheight = r_bloomstate.bloomheight;
3805 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3806 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3807 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3808 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3811 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))
3813 Cvar_SetValueQuick(&r_hdr, 0);
3814 Cvar_SetValueQuick(&r_bloom, 0);
3815 Cvar_SetValueQuick(&r_motionblur, 0);
3816 Cvar_SetValueQuick(&r_damageblur, 0);
3819 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)))
3820 screentexturewidth = screentextureheight = 0;
3821 if (!r_hdr.integer && !r_bloom.integer)
3822 bloomtexturewidth = bloomtextureheight = 0;
3824 // allocate textures as needed
3825 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3827 if (r_bloomstate.texture_screen)
3828 R_FreeTexture(r_bloomstate.texture_screen);
3829 r_bloomstate.texture_screen = NULL;
3830 r_bloomstate.screentexturewidth = screentexturewidth;
3831 r_bloomstate.screentextureheight = screentextureheight;
3832 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3833 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);
3835 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3837 if (r_bloomstate.texture_bloom)
3838 R_FreeTexture(r_bloomstate.texture_bloom);
3839 r_bloomstate.texture_bloom = NULL;
3840 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3841 r_bloomstate.bloomtextureheight = bloomtextureheight;
3842 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3843 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);
3846 // when doing a reduced render (HDR) we want to use a smaller area
3847 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
3848 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3849 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3850 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
3851 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
3853 // set up a texcoord array for the full resolution screen image
3854 // (we have to keep this around to copy back during final render)
3855 r_bloomstate.screentexcoord2f[0] = 0;
3856 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3857 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3858 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3859 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3860 r_bloomstate.screentexcoord2f[5] = 0;
3861 r_bloomstate.screentexcoord2f[6] = 0;
3862 r_bloomstate.screentexcoord2f[7] = 0;
3864 // set up a texcoord array for the reduced resolution bloom image
3865 // (which will be additive blended over the screen image)
3866 r_bloomstate.bloomtexcoord2f[0] = 0;
3867 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3868 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3869 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3870 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3871 r_bloomstate.bloomtexcoord2f[5] = 0;
3872 r_bloomstate.bloomtexcoord2f[6] = 0;
3873 r_bloomstate.bloomtexcoord2f[7] = 0;
3875 if (r_hdr.integer || r_bloom.integer)
3877 r_bloomstate.enabled = true;
3878 r_bloomstate.hdr = r_hdr.integer != 0;
3881 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);
3884 void R_Bloom_CopyBloomTexture(float colorscale)
3886 r_refdef.stats.bloom++;
3888 // scale down screen texture to the bloom texture size
3890 R_SetViewport(&r_bloomstate.viewport);
3891 GL_BlendFunc(GL_ONE, GL_ZERO);
3892 GL_Color(colorscale, colorscale, colorscale, 1);
3893 // TODO: optimize with multitexture or GLSL
3894 R_SetupGenericShader(true);
3895 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3896 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3897 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3898 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3900 // we now have a bloom image in the framebuffer
3901 // copy it into the bloom image texture for later processing
3902 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3903 GL_ActiveTexture(0);
3905 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
3906 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
3909 void R_Bloom_CopyHDRTexture(void)
3911 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3912 GL_ActiveTexture(0);
3914 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
3915 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
3918 void R_Bloom_MakeTexture(void)
3921 float xoffset, yoffset, r, brighten;
3923 r_refdef.stats.bloom++;
3925 R_ResetViewRendering2D();
3926 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3927 R_Mesh_ColorPointer(NULL, 0, 0);
3928 R_SetupGenericShader(true);
3930 // we have a bloom image in the framebuffer
3932 R_SetViewport(&r_bloomstate.viewport);
3934 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3937 r = bound(0, r_bloom_colorexponent.value / x, 1);
3938 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3939 GL_Color(r, r, r, 1);
3940 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3941 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3942 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3943 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3945 // copy the vertically blurred bloom view to a texture
3946 GL_ActiveTexture(0);
3948 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
3949 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
3952 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3953 brighten = r_bloom_brighten.value;
3955 brighten *= r_hdr_range.value;
3956 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3957 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3959 for (dir = 0;dir < 2;dir++)
3961 // blend on at multiple vertical offsets to achieve a vertical blur
3962 // TODO: do offset blends using GLSL
3963 GL_BlendFunc(GL_ONE, GL_ZERO);
3964 for (x = -range;x <= range;x++)
3966 if (!dir){xoffset = 0;yoffset = x;}
3967 else {xoffset = x;yoffset = 0;}
3968 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3969 yoffset /= (float)r_bloomstate.bloomtextureheight;
3970 // compute a texcoord array with the specified x and y offset
3971 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3972 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3973 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3974 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3975 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3976 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3977 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3978 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3979 // this r value looks like a 'dot' particle, fading sharply to
3980 // black at the edges
3981 // (probably not realistic but looks good enough)
3982 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3983 //r = (dir ? 1.0f : brighten)/(range*2+1);
3984 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3985 GL_Color(r, r, r, 1);
3986 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3987 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3988 GL_BlendFunc(GL_ONE, GL_ONE);
3991 // copy the vertically blurred bloom view to a texture
3992 GL_ActiveTexture(0);
3994 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
3995 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
3998 // apply subtract last
3999 // (just like it would be in a GLSL shader)
4000 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4002 GL_BlendFunc(GL_ONE, GL_ZERO);
4003 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4004 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4005 GL_Color(1, 1, 1, 1);
4006 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4007 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4009 GL_BlendFunc(GL_ONE, GL_ONE);
4010 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4011 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4012 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4013 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4014 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4015 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4016 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4018 // copy the darkened bloom view to a texture
4019 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4020 GL_ActiveTexture(0);
4022 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4023 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4027 void R_HDR_RenderBloomTexture(void)
4029 int oldwidth, oldheight;
4030 float oldcolorscale;
4032 oldcolorscale = r_refdef.view.colorscale;
4033 oldwidth = r_refdef.view.width;
4034 oldheight = r_refdef.view.height;
4035 r_refdef.view.width = r_bloomstate.bloomwidth;
4036 r_refdef.view.height = r_bloomstate.bloomheight;
4038 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4039 // TODO: add exposure compensation features
4040 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4042 r_refdef.view.showdebug = false;
4043 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4045 R_ResetViewRendering3D();
4047 R_ClearScreen(r_refdef.fogenabled);
4048 if (r_timereport_active)
4049 R_TimeReport("HDRclear");
4052 if (r_timereport_active)
4053 R_TimeReport("visibility");
4055 // only do secondary renders with HDR if r_hdr is 2 or higher
4056 r_waterstate.numwaterplanes = 0;
4057 if (r_waterstate.enabled && r_hdr.integer >= 2)
4058 R_RenderWaterPlanes();
4060 r_refdef.view.showdebug = true;
4062 r_waterstate.numwaterplanes = 0;
4064 R_ResetViewRendering2D();
4066 R_Bloom_CopyHDRTexture();
4067 R_Bloom_MakeTexture();
4069 // restore the view settings
4070 r_refdef.view.width = oldwidth;
4071 r_refdef.view.height = oldheight;
4072 r_refdef.view.colorscale = oldcolorscale;
4074 R_ResetViewRendering3D();
4076 R_ClearScreen(r_refdef.fogenabled);
4077 if (r_timereport_active)
4078 R_TimeReport("viewclear");
4081 static void R_BlendView(void)
4083 if (r_bloomstate.texture_screen)
4085 // make sure the buffer is available
4086 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4088 R_ResetViewRendering2D();
4089 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4090 R_Mesh_ColorPointer(NULL, 0, 0);
4091 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4092 GL_ActiveTexture(0);CHECKGLERROR
4094 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4096 // declare variables
4098 static float avgspeed;
4100 speed = VectorLength(cl.movement_velocity);
4102 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4103 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4105 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4106 speed = bound(0, speed, 1);
4107 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4109 // calculate values into a standard alpha
4110 cl.motionbluralpha = 1 - exp(-
4112 (r_motionblur.value * speed / 80)
4114 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4117 max(0.0001, cl.time - cl.oldtime) // fps independent
4120 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4121 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4123 if (cl.motionbluralpha > 0)
4125 R_SetupGenericShader(true);
4126 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4127 GL_Color(1, 1, 1, cl.motionbluralpha);
4128 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4129 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4130 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4131 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4135 // copy view into the screen texture
4136 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
4137 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4140 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4142 unsigned int permutation =
4143 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4144 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4145 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4146 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4147 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4149 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4151 // render simple bloom effect
4152 // copy the screen and shrink it and darken it for the bloom process
4153 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4154 // make the bloom texture
4155 R_Bloom_MakeTexture();
4158 R_ResetViewRendering2D();
4159 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4160 R_Mesh_ColorPointer(NULL, 0, 0);
4161 GL_Color(1, 1, 1, 1);
4162 GL_BlendFunc(GL_ONE, GL_ZERO);
4163 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4164 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4165 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4166 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4167 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4168 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4169 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4170 if (r_glsl_permutation->loc_TintColor >= 0)
4171 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4172 if (r_glsl_permutation->loc_ClientTime >= 0)
4173 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4174 if (r_glsl_permutation->loc_PixelSize >= 0)
4175 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4176 if (r_glsl_permutation->loc_UserVec1 >= 0)
4178 float a=0, b=0, c=0, d=0;
4179 #if _MSC_VER >= 1400
4180 #define sscanf sscanf_s
4182 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4183 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4185 if (r_glsl_permutation->loc_UserVec2 >= 0)
4187 float a=0, b=0, c=0, d=0;
4188 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4189 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4191 if (r_glsl_permutation->loc_UserVec3 >= 0)
4193 float a=0, b=0, c=0, d=0;
4194 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4195 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4197 if (r_glsl_permutation->loc_UserVec4 >= 0)
4199 float a=0, b=0, c=0, d=0;
4200 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4201 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4203 if (r_glsl_permutation->loc_Saturation >= 0)
4204 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4205 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4206 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4212 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4214 // render high dynamic range bloom effect
4215 // the bloom texture was made earlier this render, so we just need to
4216 // blend it onto the screen...
4217 R_ResetViewRendering2D();
4218 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4219 R_Mesh_ColorPointer(NULL, 0, 0);
4220 R_SetupGenericShader(true);
4221 GL_Color(1, 1, 1, 1);
4222 GL_BlendFunc(GL_ONE, GL_ONE);
4223 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4224 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4225 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4226 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4228 else if (r_bloomstate.texture_bloom)
4230 // render simple bloom effect
4231 // copy the screen and shrink it and darken it for the bloom process
4232 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4233 // make the bloom texture
4234 R_Bloom_MakeTexture();
4235 // put the original screen image back in place and blend the bloom
4237 R_ResetViewRendering2D();
4238 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4239 R_Mesh_ColorPointer(NULL, 0, 0);
4240 GL_Color(1, 1, 1, 1);
4241 GL_BlendFunc(GL_ONE, GL_ZERO);
4242 // do both in one pass if possible
4243 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4244 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4245 if (r_textureunits.integer >= 2 && gl_combine.integer)
4247 R_SetupGenericTwoTextureShader(GL_ADD);
4248 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4249 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4253 R_SetupGenericShader(true);
4254 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4255 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4256 // now blend on the bloom texture
4257 GL_BlendFunc(GL_ONE, GL_ONE);
4258 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4259 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4261 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4262 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4264 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4266 // apply a color tint to the whole view
4267 R_ResetViewRendering2D();
4268 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4269 R_Mesh_ColorPointer(NULL, 0, 0);
4270 R_SetupGenericShader(false);
4271 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4272 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4273 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4277 matrix4x4_t r_waterscrollmatrix;
4279 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4281 if (r_refdef.fog_density)
4283 r_refdef.fogcolor[0] = r_refdef.fog_red;
4284 r_refdef.fogcolor[1] = r_refdef.fog_green;
4285 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4289 VectorCopy(r_refdef.fogcolor, fogvec);
4290 // color.rgb *= ContrastBoost * SceneBrightness;
4291 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4292 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4293 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4294 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4299 void R_UpdateVariables(void)
4303 r_refdef.scene.ambient = r_ambient.value;
4305 r_refdef.farclip = 4096;
4306 if (r_refdef.scene.worldmodel)
4307 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4308 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4310 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4311 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4312 r_refdef.polygonfactor = 0;
4313 r_refdef.polygonoffset = 0;
4314 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4315 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4317 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4318 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4319 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4320 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4321 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4322 if (r_showsurfaces.integer)
4324 r_refdef.scene.rtworld = false;
4325 r_refdef.scene.rtworldshadows = false;
4326 r_refdef.scene.rtdlight = false;
4327 r_refdef.scene.rtdlightshadows = false;
4328 r_refdef.lightmapintensity = 0;
4331 if (gamemode == GAME_NEHAHRA)
4333 if (gl_fogenable.integer)
4335 r_refdef.oldgl_fogenable = true;
4336 r_refdef.fog_density = gl_fogdensity.value;
4337 r_refdef.fog_red = gl_fogred.value;
4338 r_refdef.fog_green = gl_foggreen.value;
4339 r_refdef.fog_blue = gl_fogblue.value;
4340 r_refdef.fog_alpha = 1;
4341 r_refdef.fog_start = 0;
4342 r_refdef.fog_end = gl_skyclip.value;
4344 else if (r_refdef.oldgl_fogenable)
4346 r_refdef.oldgl_fogenable = false;
4347 r_refdef.fog_density = 0;
4348 r_refdef.fog_red = 0;
4349 r_refdef.fog_green = 0;
4350 r_refdef.fog_blue = 0;
4351 r_refdef.fog_alpha = 0;
4352 r_refdef.fog_start = 0;
4353 r_refdef.fog_end = 0;
4357 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4358 r_refdef.fog_start = max(0, r_refdef.fog_start);
4359 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4361 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4363 if (r_refdef.fog_density && r_drawfog.integer)
4365 r_refdef.fogenabled = true;
4366 // this is the point where the fog reaches 0.9986 alpha, which we
4367 // consider a good enough cutoff point for the texture
4368 // (0.9986 * 256 == 255.6)
4369 if (r_fog_exp2.integer)
4370 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4372 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4373 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4374 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4375 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4376 // fog color was already set
4377 // update the fog texture
4378 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)
4379 R_BuildFogTexture();
4382 r_refdef.fogenabled = false;
4384 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4386 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4388 // build GLSL gamma texture
4389 #define RAMPWIDTH 256
4390 unsigned short ramp[RAMPWIDTH * 3];
4391 unsigned char rampbgr[RAMPWIDTH][4];
4394 r_texture_gammaramps_serial = vid_gammatables_serial;
4396 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4397 for(i = 0; i < RAMPWIDTH; ++i)
4399 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4400 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4401 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4404 if (r_texture_gammaramps)
4406 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4410 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);
4416 // remove GLSL gamma texture
4420 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4421 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4427 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4428 if( scenetype != r_currentscenetype ) {
4429 // store the old scenetype
4430 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4431 r_currentscenetype = scenetype;
4432 // move in the new scene
4433 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4442 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4444 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4445 if( scenetype == r_currentscenetype ) {
4446 return &r_refdef.scene;
4448 return &r_scenes_store[ scenetype ];
4457 void R_RenderView(void)
4459 if (r_timereport_active)
4460 R_TimeReport("start");
4461 r_frame++; // used only by R_GetCurrentTexture
4462 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4464 R_AnimCache_NewFrame();
4466 if (r_refdef.view.isoverlay)
4468 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4469 GL_Clear( GL_DEPTH_BUFFER_BIT );
4470 R_TimeReport("depthclear");
4472 r_refdef.view.showdebug = false;
4474 r_waterstate.enabled = false;
4475 r_waterstate.numwaterplanes = 0;
4483 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4484 return; //Host_Error ("R_RenderView: NULL worldmodel");
4486 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4488 // break apart the view matrix into vectors for various purposes
4489 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4490 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4491 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4492 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4493 // make an inverted copy of the view matrix for tracking sprites
4494 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4496 R_Shadow_UpdateWorldLightSelection();
4498 R_Bloom_StartFrame();
4499 R_Water_StartFrame();
4502 if (r_timereport_active)
4503 R_TimeReport("viewsetup");
4505 R_ResetViewRendering3D();
4507 if (r_refdef.view.clear || r_refdef.fogenabled)
4509 R_ClearScreen(r_refdef.fogenabled);
4510 if (r_timereport_active)
4511 R_TimeReport("viewclear");
4513 r_refdef.view.clear = true;
4515 // this produces a bloom texture to be used in R_BlendView() later
4517 R_HDR_RenderBloomTexture();
4519 r_refdef.view.showdebug = true;
4522 if (r_timereport_active)
4523 R_TimeReport("visibility");
4525 r_waterstate.numwaterplanes = 0;
4526 if (r_waterstate.enabled)
4527 R_RenderWaterPlanes();
4530 r_waterstate.numwaterplanes = 0;
4533 if (r_timereport_active)
4534 R_TimeReport("blendview");
4536 GL_Scissor(0, 0, vid.width, vid.height);
4537 GL_ScissorTest(false);
4541 void R_RenderWaterPlanes(void)
4543 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4545 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4546 if (r_timereport_active)
4547 R_TimeReport("waterworld");
4550 // don't let sound skip if going slow
4551 if (r_refdef.scene.extraupdate)
4554 R_DrawModelsAddWaterPlanes();
4555 if (r_timereport_active)
4556 R_TimeReport("watermodels");
4558 if (r_waterstate.numwaterplanes)
4560 R_Water_ProcessPlanes();
4561 if (r_timereport_active)
4562 R_TimeReport("waterscenes");
4566 extern void R_DrawLightningBeams (void);
4567 extern void VM_CL_AddPolygonsToMeshQueue (void);
4568 extern void R_DrawPortals (void);
4569 extern cvar_t cl_locs_show;
4570 static void R_DrawLocs(void);
4571 static void R_DrawEntityBBoxes(void);
4572 void R_RenderScene(void)
4574 r_refdef.stats.renders++;
4578 // don't let sound skip if going slow
4579 if (r_refdef.scene.extraupdate)
4582 R_MeshQueue_BeginScene();
4586 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);
4588 if (cl.csqc_vidvars.drawworld)
4590 // don't let sound skip if going slow
4591 if (r_refdef.scene.extraupdate)
4594 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4596 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4597 if (r_timereport_active)
4598 R_TimeReport("worldsky");
4601 if (R_DrawBrushModelsSky() && r_timereport_active)
4602 R_TimeReport("bmodelsky");
4605 R_AnimCache_CacheVisibleEntities();
4607 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4609 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4610 if (r_timereport_active)
4611 R_TimeReport("worlddepth");
4613 if (r_depthfirst.integer >= 2)
4615 R_DrawModelsDepth();
4616 if (r_timereport_active)
4617 R_TimeReport("modeldepth");
4620 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4622 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4623 if (r_timereport_active)
4624 R_TimeReport("world");
4627 // don't let sound skip if going slow
4628 if (r_refdef.scene.extraupdate)
4632 if (r_timereport_active)
4633 R_TimeReport("models");
4635 // don't let sound skip if going slow
4636 if (r_refdef.scene.extraupdate)
4639 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4641 R_DrawModelShadows();
4642 R_ResetViewRendering3D();
4643 // don't let sound skip if going slow
4644 if (r_refdef.scene.extraupdate)
4648 R_ShadowVolumeLighting(false);
4649 if (r_timereport_active)
4650 R_TimeReport("rtlights");
4652 // don't let sound skip if going slow
4653 if (r_refdef.scene.extraupdate)
4656 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4658 R_DrawModelShadows();
4659 R_ResetViewRendering3D();
4660 // don't let sound skip if going slow
4661 if (r_refdef.scene.extraupdate)
4665 if (cl.csqc_vidvars.drawworld)
4667 R_DrawLightningBeams();
4668 if (r_timereport_active)
4669 R_TimeReport("lightning");
4672 if (r_timereport_active)
4673 R_TimeReport("decals");
4676 if (r_timereport_active)
4677 R_TimeReport("particles");
4680 if (r_timereport_active)
4681 R_TimeReport("explosions");
4684 R_SetupGenericShader(true);
4685 VM_CL_AddPolygonsToMeshQueue();
4687 if (r_refdef.view.showdebug)
4689 if (cl_locs_show.integer)
4692 if (r_timereport_active)
4693 R_TimeReport("showlocs");
4696 if (r_drawportals.integer)
4699 if (r_timereport_active)
4700 R_TimeReport("portals");
4703 if (r_showbboxes.value > 0)
4705 R_DrawEntityBBoxes();
4706 if (r_timereport_active)
4707 R_TimeReport("bboxes");
4711 R_SetupGenericShader(true);
4712 R_MeshQueue_RenderTransparent();
4713 if (r_timereport_active)
4714 R_TimeReport("drawtrans");
4716 R_SetupGenericShader(true);
4718 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))
4720 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4721 if (r_timereport_active)
4722 R_TimeReport("worlddebug");
4723 R_DrawModelsDebug();
4724 if (r_timereport_active)
4725 R_TimeReport("modeldebug");
4728 R_SetupGenericShader(true);
4730 if (cl.csqc_vidvars.drawworld)
4733 if (r_timereport_active)
4734 R_TimeReport("coronas");
4737 // don't let sound skip if going slow
4738 if (r_refdef.scene.extraupdate)
4741 R_ResetViewRendering2D();
4744 static const unsigned short bboxelements[36] =
4754 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4757 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4758 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4759 GL_DepthMask(false);
4760 GL_DepthRange(0, 1);
4761 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4762 R_Mesh_Matrix(&identitymatrix);
4763 R_Mesh_ResetTextureState();
4765 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4766 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4767 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4768 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4769 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4770 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4771 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4772 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4773 R_FillColors(color4f, 8, cr, cg, cb, ca);
4774 if (r_refdef.fogenabled)
4776 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4778 f1 = FogPoint_World(v);
4780 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4781 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4782 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4785 R_Mesh_VertexPointer(vertex3f, 0, 0);
4786 R_Mesh_ColorPointer(color4f, 0, 0);
4787 R_Mesh_ResetTextureState();
4788 R_SetupGenericShader(false);
4789 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4792 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4796 prvm_edict_t *edict;
4797 prvm_prog_t *prog_save = prog;
4799 // this function draws bounding boxes of server entities
4803 GL_CullFace(GL_NONE);
4804 R_SetupGenericShader(false);
4808 for (i = 0;i < numsurfaces;i++)
4810 edict = PRVM_EDICT_NUM(surfacelist[i]);
4811 switch ((int)edict->fields.server->solid)
4813 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4814 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4815 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4816 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4817 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4818 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4820 color[3] *= r_showbboxes.value;
4821 color[3] = bound(0, color[3], 1);
4822 GL_DepthTest(!r_showdisabledepthtest.integer);
4823 GL_CullFace(r_refdef.view.cullface_front);
4824 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4830 static void R_DrawEntityBBoxes(void)
4833 prvm_edict_t *edict;
4835 prvm_prog_t *prog_save = prog;
4837 // this function draws bounding boxes of server entities
4843 for (i = 0;i < prog->num_edicts;i++)
4845 edict = PRVM_EDICT_NUM(i);
4846 if (edict->priv.server->free)
4848 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4849 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4851 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4853 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4854 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4860 unsigned short nomodelelements[24] =
4872 float nomodelvertex3f[6*3] =
4882 float nomodelcolor4f[6*4] =
4884 0.0f, 0.0f, 0.5f, 1.0f,
4885 0.0f, 0.0f, 0.5f, 1.0f,
4886 0.0f, 0.5f, 0.0f, 1.0f,
4887 0.0f, 0.5f, 0.0f, 1.0f,
4888 0.5f, 0.0f, 0.0f, 1.0f,
4889 0.5f, 0.0f, 0.0f, 1.0f
4892 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4897 // this is only called once per entity so numsurfaces is always 1, and
4898 // surfacelist is always {0}, so this code does not handle batches
4899 R_Mesh_Matrix(&ent->matrix);
4901 if (ent->flags & EF_ADDITIVE)
4903 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4904 GL_DepthMask(false);
4906 else if (ent->alpha < 1)
4908 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4909 GL_DepthMask(false);
4913 GL_BlendFunc(GL_ONE, GL_ZERO);
4916 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4917 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4918 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4919 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4920 R_SetupGenericShader(false);
4921 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4922 if (r_refdef.fogenabled)
4925 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4926 R_Mesh_ColorPointer(color4f, 0, 0);
4927 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4928 f1 = FogPoint_World(org);
4930 for (i = 0, c = color4f;i < 6;i++, c += 4)
4932 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4933 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4934 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4938 else if (ent->alpha != 1)
4940 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4941 R_Mesh_ColorPointer(color4f, 0, 0);
4942 for (i = 0, c = color4f;i < 6;i++, c += 4)
4946 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4947 R_Mesh_ResetTextureState();
4948 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4951 void R_DrawNoModel(entity_render_t *ent)
4954 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4955 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4956 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4958 // R_DrawNoModelCallback(ent, 0);
4961 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4963 vec3_t right1, right2, diff, normal;
4965 VectorSubtract (org2, org1, normal);
4967 // calculate 'right' vector for start
4968 VectorSubtract (r_refdef.view.origin, org1, diff);
4969 CrossProduct (normal, diff, right1);
4970 VectorNormalize (right1);
4972 // calculate 'right' vector for end
4973 VectorSubtract (r_refdef.view.origin, org2, diff);
4974 CrossProduct (normal, diff, right2);
4975 VectorNormalize (right2);
4977 vert[ 0] = org1[0] + width * right1[0];
4978 vert[ 1] = org1[1] + width * right1[1];
4979 vert[ 2] = org1[2] + width * right1[2];
4980 vert[ 3] = org1[0] - width * right1[0];
4981 vert[ 4] = org1[1] - width * right1[1];
4982 vert[ 5] = org1[2] - width * right1[2];
4983 vert[ 6] = org2[0] - width * right2[0];
4984 vert[ 7] = org2[1] - width * right2[1];
4985 vert[ 8] = org2[2] - width * right2[2];
4986 vert[ 9] = org2[0] + width * right2[0];
4987 vert[10] = org2[1] + width * right2[1];
4988 vert[11] = org2[2] + width * right2[2];
4991 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4993 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)
4995 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4999 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
5000 fog = FogPoint_World(origin);
5002 R_Mesh_Matrix(&identitymatrix);
5003 GL_BlendFunc(blendfunc1, blendfunc2);
5005 GL_CullFace(GL_NONE);
5007 GL_DepthMask(false);
5008 GL_DepthRange(0, depthshort ? 0.0625 : 1);
5009 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5010 GL_DepthTest(!depthdisable);
5012 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5013 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5014 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5015 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5016 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5017 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5018 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5019 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5020 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5021 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5022 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5023 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5025 R_Mesh_VertexPointer(vertex3f, 0, 0);
5026 R_Mesh_ColorPointer(NULL, 0, 0);
5027 R_Mesh_ResetTextureState();
5028 R_SetupGenericShader(true);
5029 R_Mesh_TexBind(0, R_GetTexture(texture));
5030 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5031 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5032 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5033 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5035 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5037 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5038 GL_BlendFunc(blendfunc1, GL_ONE);
5040 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5041 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5045 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5050 VectorSet(v, x, y, z);
5051 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5052 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5054 if (i == mesh->numvertices)
5056 if (mesh->numvertices < mesh->maxvertices)
5058 VectorCopy(v, vertex3f);
5059 mesh->numvertices++;
5061 return mesh->numvertices;
5067 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5071 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5072 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5073 e = mesh->element3i + mesh->numtriangles * 3;
5074 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5076 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5077 if (mesh->numtriangles < mesh->maxtriangles)
5082 mesh->numtriangles++;
5084 element[1] = element[2];
5088 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5092 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5093 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5094 e = mesh->element3i + mesh->numtriangles * 3;
5095 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5097 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5098 if (mesh->numtriangles < mesh->maxtriangles)
5103 mesh->numtriangles++;
5105 element[1] = element[2];
5109 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5110 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5112 int planenum, planenum2;
5115 mplane_t *plane, *plane2;
5117 double temppoints[2][256*3];
5118 // figure out how large a bounding box we need to properly compute this brush
5120 for (w = 0;w < numplanes;w++)
5121 maxdist = max(maxdist, planes[w].dist);
5122 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5123 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5124 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5128 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5129 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5131 if (planenum2 == planenum)
5133 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);
5136 if (tempnumpoints < 3)
5138 // generate elements forming a triangle fan for this polygon
5139 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5143 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)
5145 texturelayer_t *layer;
5146 layer = t->currentlayers + t->currentnumlayers++;
5148 layer->depthmask = depthmask;
5149 layer->blendfunc1 = blendfunc1;
5150 layer->blendfunc2 = blendfunc2;
5151 layer->texture = texture;
5152 layer->texmatrix = *matrix;
5153 layer->color[0] = r * r_refdef.view.colorscale;
5154 layer->color[1] = g * r_refdef.view.colorscale;
5155 layer->color[2] = b * r_refdef.view.colorscale;
5156 layer->color[3] = a;
5159 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5162 index = parms[2] + r_refdef.scene.time * parms[3];
5163 index -= floor(index);
5167 case Q3WAVEFUNC_NONE:
5168 case Q3WAVEFUNC_NOISE:
5169 case Q3WAVEFUNC_COUNT:
5172 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5173 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5174 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5175 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5176 case Q3WAVEFUNC_TRIANGLE:
5178 f = index - floor(index);
5189 return (float)(parms[0] + parms[1] * f);
5192 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5197 matrix4x4_t matrix, temp;
5198 switch(tcmod->tcmod)
5202 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5203 matrix = r_waterscrollmatrix;
5205 matrix = identitymatrix;
5207 case Q3TCMOD_ENTITYTRANSLATE:
5208 // this is used in Q3 to allow the gamecode to control texcoord
5209 // scrolling on the entity, which is not supported in darkplaces yet.
5210 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5212 case Q3TCMOD_ROTATE:
5213 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5214 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5215 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5218 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5220 case Q3TCMOD_SCROLL:
5221 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5223 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5224 w = (int) tcmod->parms[0];
5225 h = (int) tcmod->parms[1];
5226 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5228 idx = (int) floor(f * w * h);
5229 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5231 case Q3TCMOD_STRETCH:
5232 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5233 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5235 case Q3TCMOD_TRANSFORM:
5236 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5237 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5238 VectorSet(tcmat + 6, 0 , 0 , 1);
5239 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5240 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5242 case Q3TCMOD_TURBULENT:
5243 // this is handled in the RSurf_PrepareVertices function
5244 matrix = identitymatrix;
5248 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5251 texture_t *R_GetCurrentTexture(texture_t *t)
5254 const entity_render_t *ent = rsurface.entity;
5255 dp_model_t *model = ent->model;
5256 q3shaderinfo_layer_tcmod_t *tcmod;
5258 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5259 return t->currentframe;
5260 t->update_lastrenderframe = r_frame;
5261 t->update_lastrenderentity = (void *)ent;
5263 // switch to an alternate material if this is a q1bsp animated material
5265 texture_t *texture = t;
5266 int s = ent->skinnum;
5267 if ((unsigned int)s >= (unsigned int)model->numskins)
5269 if (model->skinscenes)
5271 if (model->skinscenes[s].framecount > 1)
5272 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5274 s = model->skinscenes[s].firstframe;
5277 t = t + s * model->num_surfaces;
5280 // use an alternate animation if the entity's frame is not 0,
5281 // and only if the texture has an alternate animation
5282 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
5283 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5285 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5287 texture->currentframe = t;
5290 // update currentskinframe to be a qw skin or animation frame
5291 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"))
5293 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
5295 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
5296 if (developer_loading.integer)
5297 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
5298 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);
5300 t->currentskinframe = r_qwskincache_skinframe[i];
5301 if (t->currentskinframe == NULL)
5302 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5304 else if (t->numskinframes >= 2)
5305 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5306 if (t->backgroundnumskinframes >= 2)
5307 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
5309 t->currentmaterialflags = t->basematerialflags;
5310 t->currentalpha = ent->alpha;
5311 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5312 t->currentalpha *= r_wateralpha.value;
5313 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5314 t->currentalpha *= t->r_water_wateralpha;
5315 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5316 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5317 if (!(ent->flags & RENDER_LIGHT))
5318 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5319 else if (rsurface.modeltexcoordlightmap2f == NULL)
5321 // pick a model lighting mode
5322 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5323 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5325 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5327 if (ent->effects & EF_ADDITIVE)
5328 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5329 else if (t->currentalpha < 1)
5330 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5331 if (ent->effects & EF_DOUBLESIDED)
5332 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5333 if (ent->effects & EF_NODEPTHTEST)
5334 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5335 if (ent->flags & RENDER_VIEWMODEL)
5336 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5337 if (t->backgroundnumskinframes)
5338 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5339 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5341 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5342 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5345 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5347 // there is no tcmod
5348 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5350 t->currenttexmatrix = r_waterscrollmatrix;
5351 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5355 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5356 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5359 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5360 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5361 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5362 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5364 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5365 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5366 t->glosstexture = r_texture_black;
5367 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5368 t->backgroundglosstexture = r_texture_black;
5369 t->specularpower = r_shadow_glossexponent.value;
5370 // TODO: store reference values for these in the texture?
5371 t->specularscale = 0;
5372 if (r_shadow_gloss.integer > 0)
5374 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5376 if (r_shadow_glossintensity.value > 0)
5378 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5379 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5380 t->specularscale = r_shadow_glossintensity.value;
5383 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5385 t->glosstexture = r_texture_white;
5386 t->backgroundglosstexture = r_texture_white;
5387 t->specularscale = r_shadow_gloss2intensity.value;
5391 // lightmaps mode looks bad with dlights using actual texturing, so turn
5392 // off the colormap and glossmap, but leave the normalmap on as it still
5393 // accurately represents the shading involved
5394 if (gl_lightmaps.integer)
5396 t->basetexture = r_texture_grey128;
5397 t->backgroundbasetexture = NULL;
5398 t->specularscale = 0;
5399 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5402 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5403 VectorClear(t->dlightcolor);
5404 t->currentnumlayers = 0;
5405 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5408 int blendfunc1, blendfunc2;
5410 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5412 blendfunc1 = GL_SRC_ALPHA;
5413 blendfunc2 = GL_ONE;
5415 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5417 blendfunc1 = GL_SRC_ALPHA;
5418 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5420 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5422 blendfunc1 = t->customblendfunc[0];
5423 blendfunc2 = t->customblendfunc[1];
5427 blendfunc1 = GL_ONE;
5428 blendfunc2 = GL_ZERO;
5430 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5431 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5432 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5433 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5435 // fullbright is not affected by r_refdef.lightmapintensity
5436 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]);
5437 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5438 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]);
5439 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5440 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]);
5444 vec3_t ambientcolor;
5446 // set the color tint used for lights affecting this surface
5447 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5449 // q3bsp has no lightmap updates, so the lightstylevalue that
5450 // would normally be baked into the lightmap must be
5451 // applied to the color
5452 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5453 if (ent->model->type == mod_brushq3)
5454 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5455 colorscale *= r_refdef.lightmapintensity;
5456 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5457 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5458 // basic lit geometry
5459 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]);
5460 // add pants/shirt if needed
5461 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5462 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]);
5463 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5464 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]);
5465 // now add ambient passes if needed
5466 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5468 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]);
5469 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5470 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]);
5471 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5472 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]);
5475 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5476 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]);
5477 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5479 // if this is opaque use alpha blend which will darken the earlier
5482 // if this is an alpha blended material, all the earlier passes
5483 // were darkened by fog already, so we only need to add the fog
5484 // color ontop through the fog mask texture
5486 // if this is an additive blended material, all the earlier passes
5487 // were darkened by fog already, and we should not add fog color
5488 // (because the background was not darkened, there is no fog color
5489 // that was lost behind it).
5490 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]);
5494 return t->currentframe;
5497 rsurfacestate_t rsurface;
5499 void R_Mesh_ResizeArrays(int newvertices)
5502 if (rsurface.array_size >= newvertices)
5504 if (rsurface.array_modelvertex3f)
5505 Mem_Free(rsurface.array_modelvertex3f);
5506 rsurface.array_size = (newvertices + 1023) & ~1023;
5507 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5508 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5509 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5510 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5511 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5512 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5513 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5514 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5515 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5516 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5517 rsurface.array_color4f = base + rsurface.array_size * 27;
5518 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5521 void RSurf_ActiveWorldEntity(void)
5523 dp_model_t *model = r_refdef.scene.worldmodel;
5524 //if (rsurface.entity == r_refdef.scene.worldentity)
5526 rsurface.entity = r_refdef.scene.worldentity;
5527 if (rsurface.array_size < model->surfmesh.num_vertices)
5528 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5529 rsurface.matrix = identitymatrix;
5530 rsurface.inversematrix = identitymatrix;
5531 R_Mesh_Matrix(&identitymatrix);
5532 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5533 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5534 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5535 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5536 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5537 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5538 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5539 rsurface.frameblend[0].lerp = 1;
5540 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5541 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5542 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5543 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5544 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5545 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5546 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5547 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5548 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5549 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5550 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5551 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5552 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5553 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5554 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5555 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5556 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5557 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5558 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5559 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5560 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5561 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5562 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5563 rsurface.modelelement3i = model->surfmesh.data_element3i;
5564 rsurface.modelelement3s = model->surfmesh.data_element3s;
5565 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5566 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5567 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5568 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5569 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5570 rsurface.modelsurfaces = model->data_surfaces;
5571 rsurface.generatedvertex = false;
5572 rsurface.vertex3f = rsurface.modelvertex3f;
5573 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5574 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5575 rsurface.svector3f = rsurface.modelsvector3f;
5576 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5577 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5578 rsurface.tvector3f = rsurface.modeltvector3f;
5579 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5580 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5581 rsurface.normal3f = rsurface.modelnormal3f;
5582 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5583 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5584 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5587 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5589 dp_model_t *model = ent->model;
5590 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5592 rsurface.entity = (entity_render_t *)ent;
5593 if (rsurface.array_size < model->surfmesh.num_vertices)
5594 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5595 rsurface.matrix = ent->matrix;
5596 rsurface.inversematrix = ent->inversematrix;
5597 R_Mesh_Matrix(&rsurface.matrix);
5598 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5599 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5600 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5601 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5602 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5603 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5604 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5605 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5606 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5607 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5608 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5609 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5610 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5611 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5612 if (ent->model->brush.submodel)
5614 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5615 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5617 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5619 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5621 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5622 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5623 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5624 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5626 else if (wanttangents)
5628 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5629 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5630 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5631 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5632 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5634 else if (wantnormals)
5636 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5637 rsurface.modelsvector3f = NULL;
5638 rsurface.modeltvector3f = NULL;
5639 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5640 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5644 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5645 rsurface.modelsvector3f = NULL;
5646 rsurface.modeltvector3f = NULL;
5647 rsurface.modelnormal3f = NULL;
5648 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5650 rsurface.modelvertex3f_bufferobject = 0;
5651 rsurface.modelvertex3f_bufferoffset = 0;
5652 rsurface.modelsvector3f_bufferobject = 0;
5653 rsurface.modelsvector3f_bufferoffset = 0;
5654 rsurface.modeltvector3f_bufferobject = 0;
5655 rsurface.modeltvector3f_bufferoffset = 0;
5656 rsurface.modelnormal3f_bufferobject = 0;
5657 rsurface.modelnormal3f_bufferoffset = 0;
5658 rsurface.generatedvertex = true;
5662 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5663 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5664 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5665 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5666 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5667 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5668 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5669 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5670 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5671 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5672 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5673 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5674 rsurface.generatedvertex = false;
5676 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5677 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5678 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5679 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5680 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5681 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5682 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5683 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5684 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5685 rsurface.modelelement3i = model->surfmesh.data_element3i;
5686 rsurface.modelelement3s = model->surfmesh.data_element3s;
5687 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5688 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5689 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5690 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5691 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5692 rsurface.modelsurfaces = model->data_surfaces;
5693 rsurface.vertex3f = rsurface.modelvertex3f;
5694 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5695 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5696 rsurface.svector3f = rsurface.modelsvector3f;
5697 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5698 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5699 rsurface.tvector3f = rsurface.modeltvector3f;
5700 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5701 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5702 rsurface.normal3f = rsurface.modelnormal3f;
5703 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5704 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5705 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5708 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5709 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5712 int texturesurfaceindex;
5717 const float *v1, *in_tc;
5719 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5721 q3shaderinfo_deform_t *deform;
5722 // 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
5723 if (rsurface.generatedvertex)
5725 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5726 generatenormals = true;
5727 for (i = 0;i < Q3MAXDEFORMS;i++)
5729 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5731 generatetangents = true;
5732 generatenormals = true;
5734 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5735 generatenormals = true;
5737 if (generatenormals && !rsurface.modelnormal3f)
5739 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5740 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5741 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5742 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
5744 if (generatetangents && !rsurface.modelsvector3f)
5746 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5747 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5748 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5749 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5750 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5751 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5752 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);
5755 rsurface.vertex3f = rsurface.modelvertex3f;
5756 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5757 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5758 rsurface.svector3f = rsurface.modelsvector3f;
5759 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5760 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5761 rsurface.tvector3f = rsurface.modeltvector3f;
5762 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5763 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5764 rsurface.normal3f = rsurface.modelnormal3f;
5765 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5766 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5767 // if vertices are deformed (sprite flares and things in maps, possibly
5768 // water waves, bulges and other deformations), generate them into
5769 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5770 // (may be static model data or generated data for an animated model, or
5771 // the previous deform pass)
5772 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5774 switch (deform->deform)
5777 case Q3DEFORM_PROJECTIONSHADOW:
5778 case Q3DEFORM_TEXT0:
5779 case Q3DEFORM_TEXT1:
5780 case Q3DEFORM_TEXT2:
5781 case Q3DEFORM_TEXT3:
5782 case Q3DEFORM_TEXT4:
5783 case Q3DEFORM_TEXT5:
5784 case Q3DEFORM_TEXT6:
5785 case Q3DEFORM_TEXT7:
5788 case Q3DEFORM_AUTOSPRITE:
5789 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5790 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5791 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5792 VectorNormalize(newforward);
5793 VectorNormalize(newright);
5794 VectorNormalize(newup);
5795 // make deformed versions of only the model vertices used by the specified surfaces
5796 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5798 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5799 // a single autosprite surface can contain multiple sprites...
5800 for (j = 0;j < surface->num_vertices - 3;j += 4)
5802 VectorClear(center);
5803 for (i = 0;i < 4;i++)
5804 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5805 VectorScale(center, 0.25f, center);
5806 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5807 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5808 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5809 for (i = 0;i < 4;i++)
5811 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5812 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5815 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);
5816 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);
5818 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5819 rsurface.vertex3f_bufferobject = 0;
5820 rsurface.vertex3f_bufferoffset = 0;
5821 rsurface.svector3f = rsurface.array_deformedsvector3f;
5822 rsurface.svector3f_bufferobject = 0;
5823 rsurface.svector3f_bufferoffset = 0;
5824 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5825 rsurface.tvector3f_bufferobject = 0;
5826 rsurface.tvector3f_bufferoffset = 0;
5827 rsurface.normal3f = rsurface.array_deformednormal3f;
5828 rsurface.normal3f_bufferobject = 0;
5829 rsurface.normal3f_bufferoffset = 0;
5831 case Q3DEFORM_AUTOSPRITE2:
5832 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5833 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5834 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5835 VectorNormalize(newforward);
5836 VectorNormalize(newright);
5837 VectorNormalize(newup);
5838 // make deformed versions of only the model vertices used by the specified surfaces
5839 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5841 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5842 const float *v1, *v2;
5852 memset(shortest, 0, sizeof(shortest));
5853 // a single autosprite surface can contain multiple sprites...
5854 for (j = 0;j < surface->num_vertices - 3;j += 4)
5856 VectorClear(center);
5857 for (i = 0;i < 4;i++)
5858 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5859 VectorScale(center, 0.25f, center);
5860 // find the two shortest edges, then use them to define the
5861 // axis vectors for rotating around the central axis
5862 for (i = 0;i < 6;i++)
5864 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5865 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5867 Debug_PolygonBegin(NULL, 0);
5868 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5869 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);
5870 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5873 l = VectorDistance2(v1, v2);
5874 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5876 l += (1.0f / 1024.0f);
5877 if (shortest[0].length2 > l || i == 0)
5879 shortest[1] = shortest[0];
5880 shortest[0].length2 = l;
5881 shortest[0].v1 = v1;
5882 shortest[0].v2 = v2;
5884 else if (shortest[1].length2 > l || i == 1)
5886 shortest[1].length2 = l;
5887 shortest[1].v1 = v1;
5888 shortest[1].v2 = v2;
5891 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5892 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5894 Debug_PolygonBegin(NULL, 0);
5895 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5896 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);
5897 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5900 // this calculates the right vector from the shortest edge
5901 // and the up vector from the edge midpoints
5902 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5903 VectorNormalize(right);
5904 VectorSubtract(end, start, up);
5905 VectorNormalize(up);
5906 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5907 VectorSubtract(rsurface.modelorg, center, forward);
5908 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5909 VectorNegate(forward, forward);
5910 VectorReflect(forward, 0, up, forward);
5911 VectorNormalize(forward);
5912 CrossProduct(up, forward, newright);
5913 VectorNormalize(newright);
5915 Debug_PolygonBegin(NULL, 0);
5916 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);
5917 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5918 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5922 Debug_PolygonBegin(NULL, 0);
5923 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5924 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5925 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5928 // rotate the quad around the up axis vector, this is made
5929 // especially easy by the fact we know the quad is flat,
5930 // so we only have to subtract the center position and
5931 // measure distance along the right vector, and then
5932 // multiply that by the newright vector and add back the
5934 // we also need to subtract the old position to undo the
5935 // displacement from the center, which we do with a
5936 // DotProduct, the subtraction/addition of center is also
5937 // optimized into DotProducts here
5938 l = DotProduct(right, center);
5939 for (i = 0;i < 4;i++)
5941 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5942 f = DotProduct(right, v1) - l;
5943 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5946 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);
5947 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);
5949 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5950 rsurface.vertex3f_bufferobject = 0;
5951 rsurface.vertex3f_bufferoffset = 0;
5952 rsurface.svector3f = rsurface.array_deformedsvector3f;
5953 rsurface.svector3f_bufferobject = 0;
5954 rsurface.svector3f_bufferoffset = 0;
5955 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5956 rsurface.tvector3f_bufferobject = 0;
5957 rsurface.tvector3f_bufferoffset = 0;
5958 rsurface.normal3f = rsurface.array_deformednormal3f;
5959 rsurface.normal3f_bufferobject = 0;
5960 rsurface.normal3f_bufferoffset = 0;
5962 case Q3DEFORM_NORMAL:
5963 // deform the normals to make reflections wavey
5964 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5966 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5967 for (j = 0;j < surface->num_vertices;j++)
5970 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5971 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5972 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5973 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5974 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5975 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5976 VectorNormalize(normal);
5978 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);
5980 rsurface.svector3f = rsurface.array_deformedsvector3f;
5981 rsurface.svector3f_bufferobject = 0;
5982 rsurface.svector3f_bufferoffset = 0;
5983 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5984 rsurface.tvector3f_bufferobject = 0;
5985 rsurface.tvector3f_bufferoffset = 0;
5986 rsurface.normal3f = rsurface.array_deformednormal3f;
5987 rsurface.normal3f_bufferobject = 0;
5988 rsurface.normal3f_bufferoffset = 0;
5991 // deform vertex array to make wavey water and flags and such
5992 waveparms[0] = deform->waveparms[0];
5993 waveparms[1] = deform->waveparms[1];
5994 waveparms[2] = deform->waveparms[2];
5995 waveparms[3] = deform->waveparms[3];
5996 // this is how a divisor of vertex influence on deformation
5997 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5998 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5999 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6001 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6002 for (j = 0;j < surface->num_vertices;j++)
6004 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6005 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6006 // if the wavefunc depends on time, evaluate it per-vertex
6009 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6010 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6012 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6015 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6016 rsurface.vertex3f_bufferobject = 0;
6017 rsurface.vertex3f_bufferoffset = 0;
6019 case Q3DEFORM_BULGE:
6020 // deform vertex array to make the surface have moving bulges
6021 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6023 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6024 for (j = 0;j < surface->num_vertices;j++)
6026 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6027 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6030 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6031 rsurface.vertex3f_bufferobject = 0;
6032 rsurface.vertex3f_bufferoffset = 0;
6035 // deform vertex array
6036 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6037 VectorScale(deform->parms, scale, waveparms);
6038 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6040 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6041 for (j = 0;j < surface->num_vertices;j++)
6042 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6044 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6045 rsurface.vertex3f_bufferobject = 0;
6046 rsurface.vertex3f_bufferoffset = 0;
6050 // generate texcoords based on the chosen texcoord source
6051 switch(rsurface.texture->tcgen.tcgen)
6054 case Q3TCGEN_TEXTURE:
6055 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6056 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6057 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6059 case Q3TCGEN_LIGHTMAP:
6060 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6061 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6062 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6064 case Q3TCGEN_VECTOR:
6065 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6067 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6068 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)
6070 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6071 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6074 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6075 rsurface.texcoordtexture2f_bufferobject = 0;
6076 rsurface.texcoordtexture2f_bufferoffset = 0;
6078 case Q3TCGEN_ENVIRONMENT:
6079 // make environment reflections using a spheremap
6080 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6082 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6083 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6084 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6085 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6086 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6088 // identical to Q3A's method, but executed in worldspace so
6089 // carried models can be shiny too
6091 float viewer[3], d, reflected[3], worldreflected[3];
6093 VectorSubtract(rsurface.modelorg, vertex, viewer);
6094 // VectorNormalize(viewer);
6096 d = DotProduct(normal, viewer);
6098 reflected[0] = normal[0]*2*d - viewer[0];
6099 reflected[1] = normal[1]*2*d - viewer[1];
6100 reflected[2] = normal[2]*2*d - viewer[2];
6101 // note: this is proportinal to viewer, so we can normalize later
6103 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6104 VectorNormalize(worldreflected);
6106 // note: this sphere map only uses world x and z!
6107 // so positive and negative y will LOOK THE SAME.
6108 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6109 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6112 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6113 rsurface.texcoordtexture2f_bufferobject = 0;
6114 rsurface.texcoordtexture2f_bufferoffset = 0;
6117 // the only tcmod that needs software vertex processing is turbulent, so
6118 // check for it here and apply the changes if needed
6119 // and we only support that as the first one
6120 // (handling a mixture of turbulent and other tcmods would be problematic
6121 // without punting it entirely to a software path)
6122 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6124 amplitude = rsurface.texture->tcmods[0].parms[1];
6125 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6126 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6128 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6129 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)
6131 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6132 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6135 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6136 rsurface.texcoordtexture2f_bufferobject = 0;
6137 rsurface.texcoordtexture2f_bufferoffset = 0;
6139 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6140 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6141 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6142 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6145 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6148 const msurface_t *surface = texturesurfacelist[0];
6149 const msurface_t *surface2;
6154 // TODO: lock all array ranges before render, rather than on each surface
6155 if (texturenumsurfaces == 1)
6157 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6158 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);
6160 else if (r_batchmode.integer == 2)
6162 #define MAXBATCHTRIANGLES 4096
6163 int batchtriangles = 0;
6164 int batchelements[MAXBATCHTRIANGLES*3];
6165 for (i = 0;i < texturenumsurfaces;i = j)
6167 surface = texturesurfacelist[i];
6169 if (surface->num_triangles > MAXBATCHTRIANGLES)
6171 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);
6174 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6175 batchtriangles = surface->num_triangles;
6176 firstvertex = surface->num_firstvertex;
6177 endvertex = surface->num_firstvertex + surface->num_vertices;
6178 for (;j < texturenumsurfaces;j++)
6180 surface2 = texturesurfacelist[j];
6181 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6183 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6184 batchtriangles += surface2->num_triangles;
6185 firstvertex = min(firstvertex, surface2->num_firstvertex);
6186 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6188 surface2 = texturesurfacelist[j-1];
6189 numvertices = endvertex - firstvertex;
6190 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6193 else if (r_batchmode.integer == 1)
6195 for (i = 0;i < texturenumsurfaces;i = j)
6197 surface = texturesurfacelist[i];
6198 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6199 if (texturesurfacelist[j] != surface2)
6201 surface2 = texturesurfacelist[j-1];
6202 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6203 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6204 GL_LockArrays(surface->num_firstvertex, numvertices);
6205 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6210 for (i = 0;i < texturenumsurfaces;i++)
6212 surface = texturesurfacelist[i];
6213 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6214 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);
6219 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6221 int i, planeindex, vertexindex;
6225 r_waterstate_waterplane_t *p, *bestp;
6226 msurface_t *surface;
6227 if (r_waterstate.renderingscene)
6229 for (i = 0;i < texturenumsurfaces;i++)
6231 surface = texturesurfacelist[i];
6232 if (lightmaptexunit >= 0)
6233 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6234 if (deluxemaptexunit >= 0)
6235 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6236 // pick the closest matching water plane
6239 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6242 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6244 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6245 d += fabs(PlaneDiff(vert, &p->plane));
6247 if (bestd > d || !bestp)
6255 if (refractiontexunit >= 0)
6256 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6257 if (reflectiontexunit >= 0)
6258 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6262 if (refractiontexunit >= 0)
6263 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6264 if (reflectiontexunit >= 0)
6265 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6267 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6268 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);
6272 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6276 const msurface_t *surface = texturesurfacelist[0];
6277 const msurface_t *surface2;
6282 // TODO: lock all array ranges before render, rather than on each surface
6283 if (texturenumsurfaces == 1)
6285 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6286 if (deluxemaptexunit >= 0)
6287 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6288 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6289 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);
6291 else if (r_batchmode.integer == 2)
6293 #define MAXBATCHTRIANGLES 4096
6294 int batchtriangles = 0;
6295 int batchelements[MAXBATCHTRIANGLES*3];
6296 for (i = 0;i < texturenumsurfaces;i = j)
6298 surface = texturesurfacelist[i];
6299 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6300 if (deluxemaptexunit >= 0)
6301 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6303 if (surface->num_triangles > MAXBATCHTRIANGLES)
6305 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);
6308 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6309 batchtriangles = surface->num_triangles;
6310 firstvertex = surface->num_firstvertex;
6311 endvertex = surface->num_firstvertex + surface->num_vertices;
6312 for (;j < texturenumsurfaces;j++)
6314 surface2 = texturesurfacelist[j];
6315 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6317 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6318 batchtriangles += surface2->num_triangles;
6319 firstvertex = min(firstvertex, surface2->num_firstvertex);
6320 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6322 surface2 = texturesurfacelist[j-1];
6323 numvertices = endvertex - firstvertex;
6324 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6327 else if (r_batchmode.integer == 1)
6330 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6331 for (i = 0;i < texturenumsurfaces;i = j)
6333 surface = texturesurfacelist[i];
6334 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6335 if (texturesurfacelist[j] != surface2)
6337 Con_Printf(" %i", j - i);
6340 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6342 for (i = 0;i < texturenumsurfaces;i = j)
6344 surface = texturesurfacelist[i];
6345 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6346 if (deluxemaptexunit >= 0)
6347 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6348 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6349 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6352 Con_Printf(" %i", j - i);
6354 surface2 = texturesurfacelist[j-1];
6355 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6356 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6357 GL_LockArrays(surface->num_firstvertex, numvertices);
6358 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6366 for (i = 0;i < texturenumsurfaces;i++)
6368 surface = texturesurfacelist[i];
6369 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6370 if (deluxemaptexunit >= 0)
6371 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6372 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6373 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);
6378 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6381 int texturesurfaceindex;
6382 if (r_showsurfaces.integer == 2)
6384 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6386 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6387 for (j = 0;j < surface->num_triangles;j++)
6389 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6390 GL_Color(f, f, f, 1);
6391 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6397 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6399 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6400 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6401 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);
6402 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6403 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);
6408 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6410 int texturesurfaceindex;
6413 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6415 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6416 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)
6424 rsurface.lightmapcolor4f = rsurface.array_color4f;
6425 rsurface.lightmapcolor4f_bufferobject = 0;
6426 rsurface.lightmapcolor4f_bufferoffset = 0;
6429 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6431 int texturesurfaceindex;
6435 if (rsurface.lightmapcolor4f)
6437 // generate color arrays for the surfaces in this list
6438 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6440 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6441 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)
6443 f = FogPoint_Model(v);
6453 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6455 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6456 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)
6458 f = FogPoint_Model(v);
6466 rsurface.lightmapcolor4f = rsurface.array_color4f;
6467 rsurface.lightmapcolor4f_bufferobject = 0;
6468 rsurface.lightmapcolor4f_bufferoffset = 0;
6471 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6473 int texturesurfaceindex;
6477 if (!rsurface.lightmapcolor4f)
6479 // generate color arrays for the surfaces in this list
6480 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6482 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6483 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)
6485 f = FogPoint_Model(v);
6486 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6487 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6488 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6492 rsurface.lightmapcolor4f = rsurface.array_color4f;
6493 rsurface.lightmapcolor4f_bufferobject = 0;
6494 rsurface.lightmapcolor4f_bufferoffset = 0;
6497 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6499 int texturesurfaceindex;
6502 if (!rsurface.lightmapcolor4f)
6504 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6506 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6507 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)
6515 rsurface.lightmapcolor4f = rsurface.array_color4f;
6516 rsurface.lightmapcolor4f_bufferobject = 0;
6517 rsurface.lightmapcolor4f_bufferoffset = 0;
6520 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6522 int texturesurfaceindex;
6525 if (!rsurface.lightmapcolor4f)
6527 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6529 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6530 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)
6532 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6533 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6534 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6538 rsurface.lightmapcolor4f = rsurface.array_color4f;
6539 rsurface.lightmapcolor4f_bufferobject = 0;
6540 rsurface.lightmapcolor4f_bufferoffset = 0;
6543 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6546 rsurface.lightmapcolor4f = NULL;
6547 rsurface.lightmapcolor4f_bufferobject = 0;
6548 rsurface.lightmapcolor4f_bufferoffset = 0;
6549 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6550 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6551 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6552 GL_Color(r, g, b, a);
6553 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6556 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6558 // TODO: optimize applyfog && applycolor case
6559 // just apply fog if necessary, and tint the fog color array if necessary
6560 rsurface.lightmapcolor4f = NULL;
6561 rsurface.lightmapcolor4f_bufferobject = 0;
6562 rsurface.lightmapcolor4f_bufferoffset = 0;
6563 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6564 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6565 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6566 GL_Color(r, g, b, a);
6567 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6570 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6572 int texturesurfaceindex;
6576 if (texturesurfacelist[0]->lightmapinfo)
6578 // generate color arrays for the surfaces in this list
6579 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6581 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6582 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6584 if (surface->lightmapinfo->samples)
6586 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6587 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6588 VectorScale(lm, scale, c);
6589 if (surface->lightmapinfo->styles[1] != 255)
6591 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6593 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6594 VectorMA(c, scale, lm, c);
6595 if (surface->lightmapinfo->styles[2] != 255)
6598 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6599 VectorMA(c, scale, lm, c);
6600 if (surface->lightmapinfo->styles[3] != 255)
6603 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6604 VectorMA(c, scale, lm, c);
6614 rsurface.lightmapcolor4f = rsurface.array_color4f;
6615 rsurface.lightmapcolor4f_bufferobject = 0;
6616 rsurface.lightmapcolor4f_bufferoffset = 0;
6620 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6621 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6622 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6624 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6625 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6626 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6627 GL_Color(r, g, b, a);
6628 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6631 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6633 int texturesurfaceindex;
6636 float *v, *c, *c2, alpha;
6637 vec3_t ambientcolor;
6638 vec3_t diffusecolor;
6642 VectorCopy(rsurface.modellight_lightdir, lightdir);
6643 f = 0.5f * r_refdef.lightmapintensity;
6644 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6645 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6646 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6647 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6648 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6649 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6651 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6653 // generate color arrays for the surfaces in this list
6654 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6656 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6657 int numverts = surface->num_vertices;
6658 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6659 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6660 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6661 // q3-style directional shading
6662 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6664 if ((f = DotProduct(c2, lightdir)) > 0)
6665 VectorMA(ambientcolor, f, diffusecolor, c);
6667 VectorCopy(ambientcolor, c);
6675 rsurface.lightmapcolor4f = rsurface.array_color4f;
6676 rsurface.lightmapcolor4f_bufferobject = 0;
6677 rsurface.lightmapcolor4f_bufferoffset = 0;
6678 *applycolor = false;
6682 *r = ambientcolor[0];
6683 *g = ambientcolor[1];
6684 *b = ambientcolor[2];
6685 rsurface.lightmapcolor4f = NULL;
6686 rsurface.lightmapcolor4f_bufferobject = 0;
6687 rsurface.lightmapcolor4f_bufferoffset = 0;
6691 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6693 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6694 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6695 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6696 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6697 GL_Color(r, g, b, a);
6698 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6701 void RSurf_SetupDepthAndCulling(void)
6703 // submodels are biased to avoid z-fighting with world surfaces that they
6704 // may be exactly overlapping (avoids z-fighting artifacts on certain
6705 // doors and things in Quake maps)
6706 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6707 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6708 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6709 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6712 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6714 // transparent sky would be ridiculous
6715 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6717 R_SetupGenericShader(false);
6720 skyrendernow = false;
6721 // we have to force off the water clipping plane while rendering sky
6725 // restore entity matrix
6726 R_Mesh_Matrix(&rsurface.matrix);
6728 RSurf_SetupDepthAndCulling();
6730 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6731 // skymasking on them, and Quake3 never did sky masking (unlike
6732 // software Quake and software Quake2), so disable the sky masking
6733 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6734 // and skymasking also looks very bad when noclipping outside the
6735 // level, so don't use it then either.
6736 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6738 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6739 R_Mesh_ColorPointer(NULL, 0, 0);
6740 R_Mesh_ResetTextureState();
6741 if (skyrendermasked)
6743 R_SetupDepthOrShadowShader();
6744 // depth-only (masking)
6745 GL_ColorMask(0,0,0,0);
6746 // just to make sure that braindead drivers don't draw
6747 // anything despite that colormask...
6748 GL_BlendFunc(GL_ZERO, GL_ONE);
6752 R_SetupGenericShader(false);
6754 GL_BlendFunc(GL_ONE, GL_ZERO);
6756 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6757 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6758 if (skyrendermasked)
6759 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6761 R_Mesh_ResetTextureState();
6762 GL_Color(1, 1, 1, 1);
6765 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6767 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6770 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6771 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6772 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6773 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6774 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6775 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6776 if (rsurface.texture->backgroundcurrentskinframe)
6778 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6779 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6780 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6781 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6783 if(rsurface.texture->colormapping)
6785 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6786 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6788 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6789 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6790 R_Mesh_ColorPointer(NULL, 0, 0);
6792 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6794 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6796 // render background
6797 GL_BlendFunc(GL_ONE, GL_ZERO);
6799 GL_AlphaTest(false);
6801 GL_Color(1, 1, 1, 1);
6802 R_Mesh_ColorPointer(NULL, 0, 0);
6804 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6805 if (r_glsl_permutation)
6807 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6808 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6809 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6810 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6811 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6812 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6813 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);
6815 GL_LockArrays(0, 0);
6817 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6818 GL_DepthMask(false);
6819 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6820 R_Mesh_ColorPointer(NULL, 0, 0);
6822 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6823 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6824 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6827 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6828 if (!r_glsl_permutation)
6831 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6832 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6833 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6834 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6835 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6836 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6838 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6840 GL_BlendFunc(GL_ONE, GL_ZERO);
6842 GL_AlphaTest(false);
6846 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6847 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6848 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6851 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6853 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6854 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);
6856 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6860 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6861 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);
6863 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6865 GL_LockArrays(0, 0);
6868 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6870 // OpenGL 1.3 path - anything not completely ancient
6871 int texturesurfaceindex;
6872 qboolean applycolor;
6876 const texturelayer_t *layer;
6877 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6879 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6882 int layertexrgbscale;
6883 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6885 if (layerindex == 0)
6889 GL_AlphaTest(false);
6890 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6893 GL_DepthMask(layer->depthmask && writedepth);
6894 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6895 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6897 layertexrgbscale = 4;
6898 VectorScale(layer->color, 0.25f, layercolor);
6900 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6902 layertexrgbscale = 2;
6903 VectorScale(layer->color, 0.5f, layercolor);
6907 layertexrgbscale = 1;
6908 VectorScale(layer->color, 1.0f, layercolor);
6910 layercolor[3] = layer->color[3];
6911 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6912 R_Mesh_ColorPointer(NULL, 0, 0);
6913 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6914 switch (layer->type)
6916 case TEXTURELAYERTYPE_LITTEXTURE:
6917 memset(&m, 0, sizeof(m));
6918 m.tex[0] = R_GetTexture(r_texture_white);
6919 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6920 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6921 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6922 m.tex[1] = R_GetTexture(layer->texture);
6923 m.texmatrix[1] = layer->texmatrix;
6924 m.texrgbscale[1] = layertexrgbscale;
6925 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6926 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6927 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6928 R_Mesh_TextureState(&m);
6929 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6930 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6931 else if (rsurface.uselightmaptexture)
6932 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6934 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6936 case TEXTURELAYERTYPE_TEXTURE:
6937 memset(&m, 0, sizeof(m));
6938 m.tex[0] = R_GetTexture(layer->texture);
6939 m.texmatrix[0] = layer->texmatrix;
6940 m.texrgbscale[0] = layertexrgbscale;
6941 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6942 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6943 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6944 R_Mesh_TextureState(&m);
6945 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6947 case TEXTURELAYERTYPE_FOG:
6948 memset(&m, 0, sizeof(m));
6949 m.texrgbscale[0] = layertexrgbscale;
6952 m.tex[0] = R_GetTexture(layer->texture);
6953 m.texmatrix[0] = layer->texmatrix;
6954 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6955 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6956 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6958 R_Mesh_TextureState(&m);
6959 // generate a color array for the fog pass
6960 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6961 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6965 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6966 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)
6968 f = 1 - FogPoint_Model(v);
6969 c[0] = layercolor[0];
6970 c[1] = layercolor[1];
6971 c[2] = layercolor[2];
6972 c[3] = f * layercolor[3];
6975 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6978 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6980 GL_LockArrays(0, 0);
6983 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6985 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6986 GL_AlphaTest(false);
6990 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6992 // OpenGL 1.1 - crusty old voodoo path
6993 int texturesurfaceindex;
6997 const texturelayer_t *layer;
6998 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7000 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7002 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7004 if (layerindex == 0)
7008 GL_AlphaTest(false);
7009 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7012 GL_DepthMask(layer->depthmask && writedepth);
7013 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7014 R_Mesh_ColorPointer(NULL, 0, 0);
7015 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7016 switch (layer->type)
7018 case TEXTURELAYERTYPE_LITTEXTURE:
7019 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7021 // two-pass lit texture with 2x rgbscale
7022 // first the lightmap pass
7023 memset(&m, 0, sizeof(m));
7024 m.tex[0] = R_GetTexture(r_texture_white);
7025 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7026 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7027 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7028 R_Mesh_TextureState(&m);
7029 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7030 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7031 else if (rsurface.uselightmaptexture)
7032 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7034 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7035 GL_LockArrays(0, 0);
7036 // then apply the texture to it
7037 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7038 memset(&m, 0, sizeof(m));
7039 m.tex[0] = R_GetTexture(layer->texture);
7040 m.texmatrix[0] = layer->texmatrix;
7041 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7042 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7043 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7044 R_Mesh_TextureState(&m);
7045 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);
7049 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
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 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7058 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);
7060 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);
7063 case TEXTURELAYERTYPE_TEXTURE:
7064 // singletexture unlit texture with transparency support
7065 memset(&m, 0, sizeof(m));
7066 m.tex[0] = R_GetTexture(layer->texture);
7067 m.texmatrix[0] = layer->texmatrix;
7068 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7069 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7070 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7071 R_Mesh_TextureState(&m);
7072 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);
7074 case TEXTURELAYERTYPE_FOG:
7075 // singletexture fogging
7076 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7079 memset(&m, 0, sizeof(m));
7080 m.tex[0] = R_GetTexture(layer->texture);
7081 m.texmatrix[0] = layer->texmatrix;
7082 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7083 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7084 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7085 R_Mesh_TextureState(&m);
7088 R_Mesh_ResetTextureState();
7089 // generate a color array for the fog pass
7090 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7094 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7095 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)
7097 f = 1 - FogPoint_Model(v);
7098 c[0] = layer->color[0];
7099 c[1] = layer->color[1];
7100 c[2] = layer->color[2];
7101 c[3] = f * layer->color[3];
7104 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7107 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7109 GL_LockArrays(0, 0);
7112 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7114 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7115 GL_AlphaTest(false);
7119 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7123 GL_AlphaTest(false);
7124 R_Mesh_ColorPointer(NULL, 0, 0);
7125 R_Mesh_ResetTextureState();
7126 R_SetupGenericShader(false);
7128 if(rsurface.texture && rsurface.texture->currentskinframe)
7130 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7131 c[3] *= rsurface.texture->currentalpha;
7141 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7143 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7144 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7145 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7148 // brighten it up (as texture value 127 means "unlit")
7149 c[0] *= 2 * r_refdef.view.colorscale;
7150 c[1] *= 2 * r_refdef.view.colorscale;
7151 c[2] *= 2 * r_refdef.view.colorscale;
7153 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7154 c[3] *= r_wateralpha.value;
7156 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7158 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7159 GL_DepthMask(false);
7161 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7163 GL_BlendFunc(GL_ONE, GL_ONE);
7164 GL_DepthMask(false);
7166 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7168 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7169 GL_DepthMask(false);
7171 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7173 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7174 GL_DepthMask(false);
7178 GL_BlendFunc(GL_ONE, GL_ZERO);
7179 GL_DepthMask(writedepth);
7182 rsurface.lightmapcolor4f = NULL;
7184 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7186 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7188 rsurface.lightmapcolor4f = NULL;
7189 rsurface.lightmapcolor4f_bufferobject = 0;
7190 rsurface.lightmapcolor4f_bufferoffset = 0;
7192 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7194 qboolean applycolor = true;
7197 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7199 r_refdef.lightmapintensity = 1;
7200 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7201 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7205 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7207 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7208 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7209 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7212 if(!rsurface.lightmapcolor4f)
7213 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7215 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7216 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7217 if(r_refdef.fogenabled)
7218 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7220 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7221 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7224 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7227 RSurf_SetupDepthAndCulling();
7228 if (r_showsurfaces.integer == 3)
7229 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7230 else if (r_glsl.integer && gl_support_fragment_shader)
7231 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7232 else if (gl_combine.integer && r_textureunits.integer >= 2)
7233 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7235 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7239 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7242 RSurf_SetupDepthAndCulling();
7243 if (r_showsurfaces.integer == 3)
7244 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7245 else if (r_glsl.integer && gl_support_fragment_shader)
7246 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7247 else if (gl_combine.integer && r_textureunits.integer >= 2)
7248 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7250 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7254 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7257 int texturenumsurfaces, endsurface;
7259 msurface_t *surface;
7260 msurface_t *texturesurfacelist[1024];
7262 // if the model is static it doesn't matter what value we give for
7263 // wantnormals and wanttangents, so this logic uses only rules applicable
7264 // to a model, knowing that they are meaningless otherwise
7265 if (ent == r_refdef.scene.worldentity)
7266 RSurf_ActiveWorldEntity();
7267 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7268 RSurf_ActiveModelEntity(ent, false, false);
7270 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7272 for (i = 0;i < numsurfaces;i = j)
7275 surface = rsurface.modelsurfaces + surfacelist[i];
7276 texture = surface->texture;
7277 rsurface.texture = R_GetCurrentTexture(texture);
7278 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7279 // scan ahead until we find a different texture
7280 endsurface = min(i + 1024, numsurfaces);
7281 texturenumsurfaces = 0;
7282 texturesurfacelist[texturenumsurfaces++] = surface;
7283 for (;j < endsurface;j++)
7285 surface = rsurface.modelsurfaces + surfacelist[j];
7286 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7288 texturesurfacelist[texturenumsurfaces++] = surface;
7290 // render the range of surfaces
7291 if (ent == r_refdef.scene.worldentity)
7292 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7294 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7296 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7297 GL_AlphaTest(false);
7300 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7302 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7306 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7308 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7310 RSurf_SetupDepthAndCulling();
7311 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7312 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7314 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7316 RSurf_SetupDepthAndCulling();
7317 GL_AlphaTest(false);
7318 R_Mesh_ColorPointer(NULL, 0, 0);
7319 R_Mesh_ResetTextureState();
7320 R_SetupGenericShader(false);
7321 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7323 GL_BlendFunc(GL_ONE, GL_ZERO);
7324 GL_Color(0, 0, 0, 1);
7325 GL_DepthTest(writedepth);
7326 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7328 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7330 RSurf_SetupDepthAndCulling();
7331 GL_AlphaTest(false);
7332 R_Mesh_ColorPointer(NULL, 0, 0);
7333 R_Mesh_ResetTextureState();
7334 R_SetupGenericShader(false);
7335 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7337 GL_BlendFunc(GL_ONE, GL_ZERO);
7339 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7341 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7342 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7343 else if (!rsurface.texture->currentnumlayers)
7345 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7347 // transparent surfaces get pushed off into the transparent queue
7348 int surfacelistindex;
7349 const msurface_t *surface;
7350 vec3_t tempcenter, center;
7351 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7353 surface = texturesurfacelist[surfacelistindex];
7354 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7355 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7356 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7357 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7358 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7363 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7364 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7369 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7373 // break the surface list down into batches by texture and use of lightmapping
7374 for (i = 0;i < numsurfaces;i = j)
7377 // texture is the base texture pointer, rsurface.texture is the
7378 // current frame/skin the texture is directing us to use (for example
7379 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7380 // use skin 1 instead)
7381 texture = surfacelist[i]->texture;
7382 rsurface.texture = R_GetCurrentTexture(texture);
7383 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7384 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7386 // if this texture is not the kind we want, skip ahead to the next one
7387 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7391 // simply scan ahead until we find a different texture or lightmap state
7392 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7394 // render the range of surfaces
7395 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7399 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7404 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7406 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7408 RSurf_SetupDepthAndCulling();
7409 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7410 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7412 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7414 RSurf_SetupDepthAndCulling();
7415 GL_AlphaTest(false);
7416 R_Mesh_ColorPointer(NULL, 0, 0);
7417 R_Mesh_ResetTextureState();
7418 R_SetupGenericShader(false);
7419 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7421 GL_BlendFunc(GL_ONE, GL_ZERO);
7422 GL_Color(0, 0, 0, 1);
7423 GL_DepthTest(writedepth);
7424 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7426 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7428 RSurf_SetupDepthAndCulling();
7429 GL_AlphaTest(false);
7430 R_Mesh_ColorPointer(NULL, 0, 0);
7431 R_Mesh_ResetTextureState();
7432 R_SetupGenericShader(false);
7433 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7435 GL_BlendFunc(GL_ONE, GL_ZERO);
7437 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7439 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7440 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7441 else if (!rsurface.texture->currentnumlayers)
7443 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7445 // transparent surfaces get pushed off into the transparent queue
7446 int surfacelistindex;
7447 const msurface_t *surface;
7448 vec3_t tempcenter, center;
7449 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7451 surface = texturesurfacelist[surfacelistindex];
7452 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7453 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7454 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7455 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7456 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7461 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7462 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7467 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7471 // break the surface list down into batches by texture and use of lightmapping
7472 for (i = 0;i < numsurfaces;i = j)
7475 // texture is the base texture pointer, rsurface.texture is the
7476 // current frame/skin the texture is directing us to use (for example
7477 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7478 // use skin 1 instead)
7479 texture = surfacelist[i]->texture;
7480 rsurface.texture = R_GetCurrentTexture(texture);
7481 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7482 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7484 // if this texture is not the kind we want, skip ahead to the next one
7485 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7489 // simply scan ahead until we find a different texture or lightmap state
7490 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7492 // render the range of surfaces
7493 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7497 float locboxvertex3f[6*4*3] =
7499 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7500 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7501 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7502 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7503 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7504 1,0,0, 0,0,0, 0,1,0, 1,1,0
7507 unsigned short locboxelements[6*2*3] =
7517 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7520 cl_locnode_t *loc = (cl_locnode_t *)ent;
7522 float vertex3f[6*4*3];
7524 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7525 GL_DepthMask(false);
7526 GL_DepthRange(0, 1);
7527 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7529 GL_CullFace(GL_NONE);
7530 R_Mesh_Matrix(&identitymatrix);
7532 R_Mesh_VertexPointer(vertex3f, 0, 0);
7533 R_Mesh_ColorPointer(NULL, 0, 0);
7534 R_Mesh_ResetTextureState();
7535 R_SetupGenericShader(false);
7538 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7539 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7540 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7541 surfacelist[0] < 0 ? 0.5f : 0.125f);
7543 if (VectorCompare(loc->mins, loc->maxs))
7545 VectorSet(size, 2, 2, 2);
7546 VectorMA(loc->mins, -0.5f, size, mins);
7550 VectorCopy(loc->mins, mins);
7551 VectorSubtract(loc->maxs, loc->mins, size);
7554 for (i = 0;i < 6*4*3;)
7555 for (j = 0;j < 3;j++, i++)
7556 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7558 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7561 void R_DrawLocs(void)
7564 cl_locnode_t *loc, *nearestloc;
7566 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7567 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7569 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7570 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7574 void R_DrawDebugModel(entity_render_t *ent)
7576 int i, j, k, l, flagsmask;
7577 const int *elements;
7579 msurface_t *surface;
7580 dp_model_t *model = ent->model;
7583 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7585 R_Mesh_ColorPointer(NULL, 0, 0);
7586 R_Mesh_ResetTextureState();
7587 R_SetupGenericShader(false);
7588 GL_DepthRange(0, 1);
7589 GL_DepthTest(!r_showdisabledepthtest.integer);
7590 GL_DepthMask(false);
7591 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7593 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7595 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7596 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7598 if (brush->colbrushf && brush->colbrushf->numtriangles)
7600 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7601 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);
7602 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7605 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7607 if (surface->num_collisiontriangles)
7609 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7610 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);
7611 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7616 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7618 if (r_showtris.integer || r_shownormals.integer)
7620 if (r_showdisabledepthtest.integer)
7622 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7623 GL_DepthMask(false);
7627 GL_BlendFunc(GL_ONE, GL_ZERO);
7630 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7632 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7634 rsurface.texture = R_GetCurrentTexture(surface->texture);
7635 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7637 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7638 if (r_showtris.value > 0)
7640 if (!rsurface.texture->currentlayers->depthmask)
7641 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7642 else if (ent == r_refdef.scene.worldentity)
7643 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7645 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7646 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7647 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7648 R_Mesh_ColorPointer(NULL, 0, 0);
7649 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7650 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7651 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7652 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);
7653 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7656 if (r_shownormals.value < 0)
7659 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7661 VectorCopy(rsurface.vertex3f + l * 3, v);
7662 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7663 qglVertex3f(v[0], v[1], v[2]);
7664 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7665 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7666 qglVertex3f(v[0], v[1], v[2]);
7671 if (r_shownormals.value > 0)
7674 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7676 VectorCopy(rsurface.vertex3f + l * 3, v);
7677 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7678 qglVertex3f(v[0], v[1], v[2]);
7679 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7680 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7681 qglVertex3f(v[0], v[1], v[2]);
7686 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7688 VectorCopy(rsurface.vertex3f + l * 3, v);
7689 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7690 qglVertex3f(v[0], v[1], v[2]);
7691 VectorMA(v, r_shownormals.value, rsurface.tvector3f + 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, 0, r_refdef.view.colorscale, 1);
7702 qglVertex3f(v[0], v[1], v[2]);
7703 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7704 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7705 qglVertex3f(v[0], v[1], v[2]);
7712 rsurface.texture = NULL;
7716 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7717 int r_maxsurfacelist = 0;
7718 msurface_t **r_surfacelist = NULL;
7719 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7721 int i, j, endj, f, flagsmask;
7723 dp_model_t *model = r_refdef.scene.worldmodel;
7724 msurface_t *surfaces;
7725 unsigned char *update;
7726 int numsurfacelist = 0;
7730 if (r_maxsurfacelist < model->num_surfaces)
7732 r_maxsurfacelist = model->num_surfaces;
7734 Mem_Free(r_surfacelist);
7735 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7738 RSurf_ActiveWorldEntity();
7740 surfaces = model->data_surfaces;
7741 update = model->brushq1.lightmapupdateflags;
7743 // update light styles on this submodel
7744 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7746 model_brush_lightstyleinfo_t *style;
7747 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7749 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7751 int *list = style->surfacelist;
7752 style->value = r_refdef.scene.lightstylevalue[style->style];
7753 for (j = 0;j < style->numsurfaces;j++)
7754 update[list[j]] = true;
7759 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7763 R_DrawDebugModel(r_refdef.scene.worldentity);
7764 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7770 rsurface.uselightmaptexture = false;
7771 rsurface.texture = NULL;
7772 rsurface.rtlight = NULL;
7774 // add visible surfaces to draw list
7775 for (i = 0;i < model->nummodelsurfaces;i++)
7777 j = model->sortedmodelsurfaces[i];
7778 if (r_refdef.viewcache.world_surfacevisible[j])
7779 r_surfacelist[numsurfacelist++] = surfaces + j;
7781 // update lightmaps if needed
7783 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7784 if (r_refdef.viewcache.world_surfacevisible[j])
7786 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7787 // don't do anything if there were no surfaces
7788 if (!numsurfacelist)
7790 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7793 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7794 GL_AlphaTest(false);
7796 // add to stats if desired
7797 if (r_speeds.integer && !skysurfaces && !depthonly)
7799 r_refdef.stats.world_surfaces += numsurfacelist;
7800 for (j = 0;j < numsurfacelist;j++)
7801 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7803 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7806 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7808 int i, j, endj, f, flagsmask;
7810 dp_model_t *model = ent->model;
7811 msurface_t *surfaces;
7812 unsigned char *update;
7813 int numsurfacelist = 0;
7817 if (r_maxsurfacelist < model->num_surfaces)
7819 r_maxsurfacelist = model->num_surfaces;
7821 Mem_Free(r_surfacelist);
7822 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7825 // if the model is static it doesn't matter what value we give for
7826 // wantnormals and wanttangents, so this logic uses only rules applicable
7827 // to a model, knowing that they are meaningless otherwise
7828 if (ent == r_refdef.scene.worldentity)
7829 RSurf_ActiveWorldEntity();
7830 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7831 RSurf_ActiveModelEntity(ent, false, false);
7833 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7835 surfaces = model->data_surfaces;
7836 update = model->brushq1.lightmapupdateflags;
7838 // update light styles
7839 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7841 model_brush_lightstyleinfo_t *style;
7842 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7844 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7846 int *list = style->surfacelist;
7847 style->value = r_refdef.scene.lightstylevalue[style->style];
7848 for (j = 0;j < style->numsurfaces;j++)
7849 update[list[j]] = true;
7854 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7858 R_DrawDebugModel(ent);
7859 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7865 rsurface.uselightmaptexture = false;
7866 rsurface.texture = NULL;
7867 rsurface.rtlight = NULL;
7869 // add visible surfaces to draw list
7870 for (i = 0;i < model->nummodelsurfaces;i++)
7871 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7872 // don't do anything if there were no surfaces
7873 if (!numsurfacelist)
7875 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7878 // update lightmaps if needed
7880 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7882 R_BuildLightMap(ent, surfaces + j);
7883 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7884 GL_AlphaTest(false);
7886 // add to stats if desired
7887 if (r_speeds.integer && !skysurfaces && !depthonly)
7889 r_refdef.stats.entities_surfaces += numsurfacelist;
7890 for (j = 0;j < numsurfacelist;j++)
7891 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7893 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity