2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
38 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
47 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
49 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
50 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
51 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
52 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
53 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
54 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
55 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
56 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
57 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
58 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
59 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
60 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
61 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
62 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
63 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
64 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
65 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
66 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
67 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
68 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
69 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
70 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
71 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
72 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
73 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
74 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
75 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
76 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
77 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
78 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
79 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
80 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
81 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
82 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
83 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
84 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
86 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
87 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
88 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
89 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
90 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
91 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
92 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
93 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
95 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
97 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
98 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
99 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
100 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
101 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
102 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
103 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
104 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
105 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
106 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
107 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
109 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
110 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
111 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
112 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
113 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
115 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
116 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
117 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
118 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
120 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
121 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
122 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
123 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
124 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
125 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
126 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
128 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
129 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
130 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
131 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
133 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
135 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
137 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
139 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
140 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
141 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
142 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
143 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
144 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
145 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
147 extern cvar_t v_glslgamma;
149 extern qboolean v_flipped_state;
151 static struct r_bloomstate_s
156 int bloomwidth, bloomheight;
158 int screentexturewidth, screentextureheight;
159 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
161 int bloomtexturewidth, bloomtextureheight;
162 rtexture_t *texture_bloom;
164 // arrays for rendering the screen passes
165 float screentexcoord2f[8];
166 float bloomtexcoord2f[8];
167 float offsettexcoord2f[8];
169 r_viewport_t viewport;
173 r_waterstate_t r_waterstate;
175 /// shadow volume bsp struct with automatically growing nodes buffer
178 rtexture_t *r_texture_blanknormalmap;
179 rtexture_t *r_texture_white;
180 rtexture_t *r_texture_grey128;
181 rtexture_t *r_texture_black;
182 rtexture_t *r_texture_notexture;
183 rtexture_t *r_texture_whitecube;
184 rtexture_t *r_texture_normalizationcube;
185 rtexture_t *r_texture_fogattenuation;
186 rtexture_t *r_texture_gammaramps;
187 unsigned int r_texture_gammaramps_serial;
188 //rtexture_t *r_texture_fogintensity;
190 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
191 unsigned int r_numqueries;
192 unsigned int r_maxqueries;
194 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
195 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
197 /// vertex coordinates for a quad that covers the screen exactly
198 const float r_screenvertex3f[12] =
206 extern void R_DrawModelShadows(void);
208 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
211 for (i = 0;i < verts;i++)
222 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
225 for (i = 0;i < verts;i++)
235 // FIXME: move this to client?
238 if (gamemode == GAME_NEHAHRA)
240 Cvar_Set("gl_fogenable", "0");
241 Cvar_Set("gl_fogdensity", "0.2");
242 Cvar_Set("gl_fogred", "0.3");
243 Cvar_Set("gl_foggreen", "0.3");
244 Cvar_Set("gl_fogblue", "0.3");
246 r_refdef.fog_density = 0;
247 r_refdef.fog_red = 0;
248 r_refdef.fog_green = 0;
249 r_refdef.fog_blue = 0;
250 r_refdef.fog_alpha = 1;
251 r_refdef.fog_start = 0;
252 r_refdef.fog_end = 0;
255 float FogForDistance(vec_t dist)
257 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
258 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
261 float FogPoint_World(const vec3_t p)
263 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
266 float FogPoint_Model(const vec3_t p)
268 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
271 static void R_BuildBlankTextures(void)
273 unsigned char data[4];
274 data[2] = 128; // normal X
275 data[1] = 128; // normal Y
276 data[0] = 255; // normal Z
277 data[3] = 128; // height
278 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
283 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
288 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
293 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
296 static void R_BuildNoTexture(void)
299 unsigned char pix[16][16][4];
300 // this makes a light grey/dark grey checkerboard texture
301 for (y = 0;y < 16;y++)
303 for (x = 0;x < 16;x++)
305 if ((y < 8) ^ (x < 8))
321 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
324 static void R_BuildWhiteCube(void)
326 unsigned char data[6*1*1*4];
327 memset(data, 255, sizeof(data));
328 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
331 static void R_BuildNormalizationCube(void)
335 vec_t s, t, intensity;
337 unsigned char data[6][NORMSIZE][NORMSIZE][4];
338 for (side = 0;side < 6;side++)
340 for (y = 0;y < NORMSIZE;y++)
342 for (x = 0;x < NORMSIZE;x++)
344 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
345 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
380 intensity = 127.0f / sqrt(DotProduct(v, v));
381 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
382 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
383 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
384 data[side][y][x][3] = 255;
388 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
391 static void R_BuildFogTexture(void)
395 unsigned char data1[FOGWIDTH][4];
396 //unsigned char data2[FOGWIDTH][4];
399 r_refdef.fogmasktable_start = r_refdef.fog_start;
400 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
401 r_refdef.fogmasktable_range = r_refdef.fogrange;
402 r_refdef.fogmasktable_density = r_refdef.fog_density;
404 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
405 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
407 d = (x * r - r_refdef.fogmasktable_start);
408 if(developer.integer >= 100)
409 Con_Printf("%f ", d);
411 if (r_fog_exp2.integer)
412 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
414 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
415 if(developer.integer >= 100)
416 Con_Printf(" : %f ", alpha);
417 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
418 if(developer.integer >= 100)
419 Con_Printf(" = %f\n", alpha);
420 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
423 for (x = 0;x < FOGWIDTH;x++)
425 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
430 //data2[x][0] = 255 - b;
431 //data2[x][1] = 255 - b;
432 //data2[x][2] = 255 - b;
435 if (r_texture_fogattenuation)
437 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
438 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
442 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
443 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
447 static const char *builtinshaderstring =
448 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
449 "// written by Forest 'LordHavoc' Hale\n"
450 "#ifdef USESHADOWMAPRECT\n"
451 "#extension GL_ARB_texture_rectangle : enable\n"
453 "#ifdef USESHADOWMAP2D\n"
454 "# ifdef HASTEXTUREGATHER\n"
455 "# extension GL_ARB_texture_gather : enable\n"
457 "# ifdef HASTEXTURE4\n"
458 "# extension GL_AMD_texture_texture4 : enable\n"
459 "# define textureGather texture4\n"
463 "#ifdef USESHADOWMAPCUBE\n"
464 "#extension GL_EXT_gpu_shader4 : enable\n"
467 "// common definitions between vertex shader and fragment shader:\n"
469 "//#ifdef __GLSL_CG_DATA_TYPES\n"
470 "//# define myhalf half\n"
471 "//# define myhalf2 half2\n"
472 "//# define myhalf3half3\n"
473 "//# define myhalf4 half4\n"
475 "# define myhalf float\n"
476 "# define myhalf2 vec2\n"
477 "# define myhalf3 vec3\n"
478 "# define myhalf4 vec4\n"
481 "#ifdef MODE_DEPTH_OR_SHADOW\n"
483 "# ifdef VERTEX_SHADER\n"
486 " gl_Position = ftransform();\n"
491 "#ifdef MODE_SHOWDEPTH\n"
492 "# ifdef VERTEX_SHADER\n"
495 " gl_Position = ftransform();\n"
496 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
499 "# ifdef FRAGMENT_SHADER\n"
502 " gl_FragColor = gl_Color;\n"
506 "#else // !MODE_SHOWDEPTH\n"
508 "#ifdef MODE_POSTPROCESS\n"
509 "# ifdef VERTEX_SHADER\n"
512 " gl_FrontColor = gl_Color;\n"
513 " gl_Position = ftransform();\n"
514 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
516 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
520 "# ifdef FRAGMENT_SHADER\n"
522 "uniform sampler2D Texture_First;\n"
524 "uniform sampler2D Texture_Second;\n"
526 "#ifdef USEGAMMARAMPS\n"
527 "uniform sampler2D Texture_GammaRamps;\n"
529 "#ifdef USESATURATION\n"
530 "uniform float Saturation;\n"
532 "#ifdef USEVIEWTINT\n"
533 "uniform vec4 TintColor;\n"
535 "//uncomment these if you want to use them:\n"
536 "uniform vec4 UserVec1;\n"
537 "// uniform vec4 UserVec2;\n"
538 "// uniform vec4 UserVec3;\n"
539 "// uniform vec4 UserVec4;\n"
540 "// uniform float ClientTime;\n"
541 "uniform vec2 PixelSize;\n"
544 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
546 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
548 "#ifdef USEVIEWTINT\n"
549 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
552 "#ifdef USEPOSTPROCESSING\n"
553 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
554 "// 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"
555 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
556 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
557 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
558 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
559 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
560 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
563 "#ifdef USESATURATION\n"
564 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
565 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
566 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
567 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
570 "#ifdef USEGAMMARAMPS\n"
571 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
572 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
573 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
580 "#ifdef MODE_GENERIC\n"
581 "# ifdef VERTEX_SHADER\n"
584 " gl_FrontColor = gl_Color;\n"
585 "# ifdef USEDIFFUSE\n"
586 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
588 "# ifdef USESPECULAR\n"
589 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
591 " gl_Position = ftransform();\n"
594 "# ifdef FRAGMENT_SHADER\n"
596 "# ifdef USEDIFFUSE\n"
597 "uniform sampler2D Texture_First;\n"
599 "# ifdef USESPECULAR\n"
600 "uniform sampler2D Texture_Second;\n"
605 " gl_FragColor = gl_Color;\n"
606 "# ifdef USEDIFFUSE\n"
607 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
610 "# ifdef USESPECULAR\n"
611 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
613 "# ifdef USECOLORMAPPING\n"
614 " gl_FragColor *= tex2;\n"
617 " gl_FragColor += tex2;\n"
619 "# ifdef USEVERTEXTEXTUREBLEND\n"
620 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
625 "#else // !MODE_GENERIC\n"
627 "varying vec2 TexCoord;\n"
628 "#ifdef USEVERTEXTEXTUREBLEND\n"
629 "varying vec2 TexCoord2;\n"
631 "varying vec2 TexCoordLightmap;\n"
633 "#ifdef MODE_LIGHTSOURCE\n"
634 "varying vec3 CubeVector;\n"
637 "#ifdef MODE_LIGHTSOURCE\n"
638 "varying vec3 LightVector;\n"
640 "#ifdef MODE_LIGHTDIRECTION\n"
641 "varying vec3 LightVector;\n"
644 "varying vec3 EyeVector;\n"
646 "varying vec3 EyeVectorModelSpace;\n"
649 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
650 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
651 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
653 "#ifdef MODE_WATER\n"
654 "varying vec4 ModelViewProjectionPosition;\n"
656 "#ifdef MODE_REFRACTION\n"
657 "varying vec4 ModelViewProjectionPosition;\n"
659 "#ifdef USEREFLECTION\n"
660 "varying vec4 ModelViewProjectionPosition;\n"
667 "// vertex shader specific:\n"
668 "#ifdef VERTEX_SHADER\n"
670 "uniform vec3 LightPosition;\n"
671 "uniform vec3 EyePosition;\n"
672 "uniform vec3 LightDir;\n"
674 "// 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"
678 " gl_FrontColor = gl_Color;\n"
679 " // copy the surface texcoord\n"
680 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
681 "#ifdef USEVERTEXTEXTUREBLEND\n"
682 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
684 "#ifndef MODE_LIGHTSOURCE\n"
685 "# ifndef MODE_LIGHTDIRECTION\n"
686 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
690 "#ifdef MODE_LIGHTSOURCE\n"
691 " // transform vertex position into light attenuation/cubemap space\n"
692 " // (-1 to +1 across the light box)\n"
693 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
695 " // transform unnormalized light direction into tangent space\n"
696 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
697 " // normalize it per pixel)\n"
698 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
699 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
700 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
701 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
704 "#ifdef MODE_LIGHTDIRECTION\n"
705 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
706 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
707 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
710 " // transform unnormalized eye direction into tangent space\n"
712 " vec3 EyeVectorModelSpace;\n"
714 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
715 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
716 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
717 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
719 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
720 " VectorS = gl_MultiTexCoord1.xyz;\n"
721 " VectorT = gl_MultiTexCoord2.xyz;\n"
722 " VectorR = gl_MultiTexCoord3.xyz;\n"
725 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
726 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
727 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
728 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
731 "// transform vertex to camera space, using ftransform to match non-VS\n"
733 " gl_Position = ftransform();\n"
735 "#ifdef MODE_WATER\n"
736 " ModelViewProjectionPosition = gl_Position;\n"
738 "#ifdef MODE_REFRACTION\n"
739 " ModelViewProjectionPosition = gl_Position;\n"
741 "#ifdef USEREFLECTION\n"
742 " ModelViewProjectionPosition = gl_Position;\n"
746 "#endif // VERTEX_SHADER\n"
751 "// fragment shader specific:\n"
752 "#ifdef FRAGMENT_SHADER\n"
754 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
755 "uniform sampler2D Texture_Normal;\n"
756 "uniform sampler2D Texture_Color;\n"
757 "uniform sampler2D Texture_Gloss;\n"
758 "uniform sampler2D Texture_Glow;\n"
759 "uniform sampler2D Texture_SecondaryNormal;\n"
760 "uniform sampler2D Texture_SecondaryColor;\n"
761 "uniform sampler2D Texture_SecondaryGloss;\n"
762 "uniform sampler2D Texture_SecondaryGlow;\n"
763 "uniform sampler2D Texture_Pants;\n"
764 "uniform sampler2D Texture_Shirt;\n"
765 "uniform sampler2D Texture_FogMask;\n"
766 "uniform sampler2D Texture_Lightmap;\n"
767 "uniform sampler2D Texture_Deluxemap;\n"
768 "uniform sampler2D Texture_Refraction;\n"
769 "uniform sampler2D Texture_Reflection;\n"
770 "uniform sampler2D Texture_Attenuation;\n"
771 "uniform samplerCube Texture_Cube;\n"
773 "#define showshadowmap 0\n"
775 "#ifdef USESHADOWMAPRECT\n"
776 "# ifdef USESHADOWSAMPLER\n"
777 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
779 "uniform sampler2DRect Texture_ShadowMapRect;\n"
783 "#ifdef USESHADOWMAP2D\n"
784 "# ifdef USESHADOWSAMPLER\n"
785 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
787 "uniform sampler2D Texture_ShadowMap2D;\n"
791 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
792 "uniform samplerCube Texture_CubeProjection;\n"
795 "#ifdef USESHADOWMAPCUBE\n"
796 "# ifdef USESHADOWSAMPLER\n"
797 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
799 "uniform samplerCube Texture_ShadowMapCube;\n"
803 "uniform myhalf3 LightColor;\n"
804 "uniform myhalf3 AmbientColor;\n"
805 "uniform myhalf3 DiffuseColor;\n"
806 "uniform myhalf3 SpecularColor;\n"
807 "uniform myhalf3 Color_Pants;\n"
808 "uniform myhalf3 Color_Shirt;\n"
809 "uniform myhalf3 FogColor;\n"
811 "uniform myhalf4 TintColor;\n"
814 "//#ifdef MODE_WATER\n"
815 "uniform vec4 DistortScaleRefractReflect;\n"
816 "uniform vec4 ScreenScaleRefractReflect;\n"
817 "uniform vec4 ScreenCenterRefractReflect;\n"
818 "uniform myhalf4 RefractColor;\n"
819 "uniform myhalf4 ReflectColor;\n"
820 "uniform myhalf ReflectFactor;\n"
821 "uniform myhalf ReflectOffset;\n"
823 "//# ifdef MODE_REFRACTION\n"
824 "//uniform vec4 DistortScaleRefractReflect;\n"
825 "//uniform vec4 ScreenScaleRefractReflect;\n"
826 "//uniform vec4 ScreenCenterRefractReflect;\n"
827 "//uniform myhalf4 RefractColor;\n"
828 "//# ifdef USEREFLECTION\n"
829 "//uniform myhalf4 ReflectColor;\n"
832 "//# ifdef USEREFLECTION\n"
833 "//uniform vec4 DistortScaleRefractReflect;\n"
834 "//uniform vec4 ScreenScaleRefractReflect;\n"
835 "//uniform vec4 ScreenCenterRefractReflect;\n"
836 "//uniform myhalf4 ReflectColor;\n"
841 "uniform myhalf GlowScale;\n"
842 "uniform myhalf SceneBrightness;\n"
844 "uniform float OffsetMapping_Scale;\n"
845 "uniform float OffsetMapping_Bias;\n"
846 "uniform float FogRangeRecip;\n"
848 "uniform myhalf AmbientScale;\n"
849 "uniform myhalf DiffuseScale;\n"
850 "uniform myhalf SpecularScale;\n"
851 "uniform myhalf SpecularPower;\n"
853 "#ifdef USEOFFSETMAPPING\n"
854 "vec2 OffsetMapping(vec2 TexCoord)\n"
856 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
857 " // 14 sample relief mapping: linear search and then binary search\n"
858 " // this basically steps forward a small amount repeatedly until it finds\n"
859 " // itself inside solid, then jitters forward and back using decreasing\n"
860 " // amounts to find the impact\n"
861 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
862 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
863 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
864 " vec3 RT = vec3(TexCoord, 1);\n"
865 " OffsetVector *= 0.1;\n"
866 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
867 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
868 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
869 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
870 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
871 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
872 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
873 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
874 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
875 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
876 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
877 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
878 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
879 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
882 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
883 " // this basically moves forward the full distance, and then backs up based\n"
884 " // on height of samples\n"
885 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
886 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
887 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
888 " TexCoord += OffsetVector;\n"
889 " OffsetVector *= 0.333;\n"
890 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
891 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
892 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
893 " return TexCoord;\n"
896 "#endif // USEOFFSETMAPPING\n"
898 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
899 "uniform vec4 ShadowMap_TextureScale;\n"
900 "uniform vec4 ShadowMap_Parameters;\n"
903 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
904 "vec3 GetShadowMapTC2D(vec3 dir)\n"
906 " vec3 adir = abs(dir);\n"
911 " if (adir.x > adir.y)\n"
913 " if (adir.x > adir.z)\n"
916 " if (dir.x >= 0.0)\n"
919 " tc = vec2(-dir.z, -dir.y);\n"
920 " offset = vec2(0.5, 0.5);\n"
925 " tc = vec2( dir.z, -dir.y);\n"
926 " offset = vec2(1.5, 0.5);\n"
932 " if (dir.z >= 0.0)\n"
935 " tc = vec2( dir.x, -dir.y);\n"
936 " offset = vec2(0.5, 2.5);\n"
941 " tc = vec2(-dir.x, -dir.y);\n"
942 " offset = vec2(1.5, 2.5);\n"
948 " if (adir.y > adir.z)\n"
951 " if (dir.y >= 0.0)\n"
954 " tc = vec2( dir.x, dir.z);\n"
955 " offset = vec2(0.5, 1.5);\n"
960 " tc = vec2( dir.x, -dir.z);\n"
961 " offset = vec2(1.5, 1.5);\n"
967 " if (dir.z >= 0.0)\n"
970 " tc = vec2(dir.x, -dir.y);\n"
971 " offset = vec2(0.5, 2.5);\n"
976 " tc = vec2(-dir.x, -dir.y);\n"
977 " offset = vec2(1.5, 2.5);\n"
982 " return vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma + vec3(offset * ShadowMap_Parameters.y, ShadowMap_Parameters.z);\n"
984 "# ifdef USESHADOWMAPRECT \n"
985 " 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"
987 " return vec3(textureCube(Texture_CubeProjection, dir.xyz).ra, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
991 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
993 "#ifdef USESHADOWMAPCUBE\n"
994 "vec4 GetShadowMapTCCube(vec3 dir)\n"
996 " vec3 adir = abs(dir);\n"
997 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1001 "#if !showshadowmap\n"
1002 "# ifdef USESHADOWMAPRECT\n"
1003 "float ShadowMapCompare(vec3 dir)\n"
1005 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1007 "# ifdef USESHADOWSAMPLER\n"
1009 "# ifdef USESHADOWMAPPCF\n"
1010 " f = dot(vec4(0.25),\n"
1011 " vec4(shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3(-0.4, 1.0, 0.0)).r,\n"
1012 " shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3(-1.0, -0.4, 0.0)).r,\n"
1013 " shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3( 0.4, -1.0, 0.0)).r,\n"
1014 " shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3( 1.0, 0.4, 0.0)).r));\n"
1016 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1021 "# ifdef USESHADOWMAPPCF\n"
1022 "# if defined(HASTEXTUREGATHER) || defined(HASTEXTURE4)\n"
1023 " vec2 offset = fract(shadowmaptc.xy - 0.5);\n"
1024 " vec4 group1 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, -1.0))),\n"
1025 " group2 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, -1.0))),\n"
1026 " group3 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, 1.0))),\n"
1027 " group4 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, 1.0))),\n"
1028 " cols = vec4(group1.ab, group2.ab) + vec4(group3.rg, group4.rg) +\n"
1029 " mix(vec4(group1.rg, group2.rg), vec4(group3.ab, group4.ab), offset.y);\n"
1030 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1032 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1033 " vec4 row1 = step(shadowmaptc.z,\n"
1034 " vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, -1.0)).r,\n"
1035 " texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0, -1.0)).r,\n"
1036 " texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, -1.0)).r,\n"
1037 " texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, -1.0)).r)),\n"
1038 " row2 = step(shadowmaptc.z,\n"
1039 " vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, 0.0)).r,\n"
1040 " texture2DRect(Texture_ShadowMapRect, center).r,\n"
1041 " texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, 0.0)).r,\n"
1042 " texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, 0.0)).r)),\n"
1043 " row3 = step(shadowmaptc.z,\n"
1044 " vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, 1.0)).r,\n"
1045 " texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0, 1.0)).r,\n"
1046 " texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, 1.0)).r,\n"
1047 " texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, 1.0)).r)),\n"
1048 " row4 = step(shadowmaptc.z,\n"
1049 " vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, 2.0)).r,\n"
1050 " texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0, 2.0)).r,\n"
1051 " texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, 2.0)).r,\n"
1052 " texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, 2.0)).r)),\n"
1053 " cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1054 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1056 " vec2 offset = fract(shadowmaptc.xy);\n"
1057 " vec3 row1 = step(shadowmaptc.z,\n"
1058 " vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, -1.0)).r,\n"
1059 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 0.0, -1.0)).r,\n"
1060 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, -1.0)).r)),\n"
1061 " row2 = step(shadowmaptc.z,\n"
1062 " vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, 0.0)).r,\n"
1063 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r,\n"
1064 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, 0.0)).r)),\n"
1065 " row3 = step(shadowmaptc.z,\n"
1066 " vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, 1.0)).r,\n"
1067 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 0.0, 1.0)).r,\n"
1068 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, 1.0)).r)),\n"
1069 " cols = row2 + mix(row1, row3, offset.y);\n"
1070 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1073 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1081 "# ifdef USESHADOWMAP2D\n"
1082 "float ShadowMapCompare(vec3 dir)\n"
1084 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1086 "# ifdef USESHADOWSAMPLER\n"
1087 " f = shadow2D(Texture_ShadowMap2D, shadowmaptc).r;\n"
1089 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy).r);\n"
1095 "# ifdef USESHADOWMAPCUBE\n"
1096 "float ShadowMapCompare(vec3 dir)\n"
1098 " // apply depth texture cubemap as light filter\n"
1099 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1101 "# ifdef USESHADOWSAMPLER\n"
1102 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1104 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1111 "#ifdef MODE_WATER\n"
1116 "#ifdef USEOFFSETMAPPING\n"
1117 " // apply offsetmapping\n"
1118 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1119 "#define TexCoord TexCoordOffset\n"
1122 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1123 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1124 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1125 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1126 " // FIXME temporary hack to detect the case that the reflection\n"
1127 " // gets blackened at edges due to leaving the area that contains actual\n"
1129 " // Remove this 'ack once we have a better way to stop this thing from\n"
1131 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1132 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1133 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1134 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1135 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1136 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1137 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1138 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1139 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1140 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1141 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1142 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1145 "#else // !MODE_WATER\n"
1146 "#ifdef MODE_REFRACTION\n"
1148 "// refraction pass\n"
1151 "#ifdef USEOFFSETMAPPING\n"
1152 " // apply offsetmapping\n"
1153 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1154 "#define TexCoord TexCoordOffset\n"
1157 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1158 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1159 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1160 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1161 " // FIXME temporary hack to detect the case that the reflection\n"
1162 " // gets blackened at edges due to leaving the area that contains actual\n"
1164 " // Remove this 'ack once we have a better way to stop this thing from\n"
1166 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1167 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1168 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1169 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1170 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1171 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1174 "#else // !MODE_REFRACTION\n"
1177 "#ifdef USEOFFSETMAPPING\n"
1178 " // apply offsetmapping\n"
1179 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1180 "#define TexCoord TexCoordOffset\n"
1183 " // combine the diffuse textures (base, pants, shirt)\n"
1184 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1185 "#ifdef USECOLORMAPPING\n"
1186 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1188 "#ifdef USEVERTEXTEXTUREBLEND\n"
1189 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1190 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1191 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1192 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1194 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1197 "#ifdef USEDIFFUSE\n"
1198 " // get the surface normal and the gloss color\n"
1199 "# ifdef USEVERTEXTEXTUREBLEND\n"
1200 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1201 "# ifdef USESPECULAR\n"
1202 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1205 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1206 "# ifdef USESPECULAR\n"
1207 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1214 "#ifdef MODE_LIGHTSOURCE\n"
1215 " // light source\n"
1217 " // calculate surface normal, light normal, and specular normal\n"
1218 " // compute color intensity for the two textures (colormap and glossmap)\n"
1219 " // scale by light color and attenuation as efficiently as possible\n"
1220 " // (do as much scalar math as possible rather than vector math)\n"
1221 "# ifdef USEDIFFUSE\n"
1222 " // get the light normal\n"
1223 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1225 "# ifdef USESPECULAR\n"
1226 "# ifndef USEEXACTSPECULARMATH\n"
1227 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1230 " // calculate directional shading\n"
1231 "# ifdef USEEXACTSPECULARMATH\n"
1232 " 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"
1234 " 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"
1237 "# ifdef USEDIFFUSE\n"
1238 " // calculate directional shading\n"
1239 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1241 " // calculate directionless shading\n"
1242 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1246 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1247 "#if !showshadowmap\n"
1248 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1252 "# ifdef USECUBEFILTER\n"
1253 " // apply light cubemap filter\n"
1254 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1255 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1257 "#endif // MODE_LIGHTSOURCE\n"
1262 "#ifdef MODE_LIGHTDIRECTION\n"
1263 " // directional model lighting\n"
1264 "# ifdef USEDIFFUSE\n"
1265 " // get the light normal\n"
1266 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1268 "# ifdef USESPECULAR\n"
1269 " // calculate directional shading\n"
1270 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1271 "# ifdef USEEXACTSPECULARMATH\n"
1272 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1274 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1275 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1278 "# ifdef USEDIFFUSE\n"
1280 " // calculate directional shading\n"
1281 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1283 " color.rgb *= AmbientColor;\n"
1286 "#endif // MODE_LIGHTDIRECTION\n"
1291 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1292 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1294 " // get the light normal\n"
1295 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1296 " myhalf3 diffusenormal;\n"
1297 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1298 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1299 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1300 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1301 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1302 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1303 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1304 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1305 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1306 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1307 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1308 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1309 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1310 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1311 "# ifdef USESPECULAR\n"
1312 "# ifdef USEEXACTSPECULARMATH\n"
1313 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1315 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1316 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1320 " // apply lightmap color\n"
1321 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1322 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1327 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1328 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1330 " // get the light normal\n"
1331 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1332 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1333 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1334 "# ifdef USESPECULAR\n"
1335 "# ifdef USEEXACTSPECULARMATH\n"
1336 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1338 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1339 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1343 " // apply lightmap color\n"
1344 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1345 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1350 "#ifdef MODE_LIGHTMAP\n"
1351 " // apply lightmap color\n"
1352 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1353 "#endif // MODE_LIGHTMAP\n"
1358 "#ifdef MODE_VERTEXCOLOR\n"
1359 " // apply lightmap color\n"
1360 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1361 "#endif // MODE_VERTEXCOLOR\n"
1366 "#ifdef MODE_FLATCOLOR\n"
1367 "#endif // MODE_FLATCOLOR\n"
1375 " color *= TintColor;\n"
1378 "#ifdef USEVERTEXTEXTUREBLEND\n"
1379 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1381 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1385 " color.rgb *= SceneBrightness;\n"
1387 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1389 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1392 " // 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"
1393 "#ifdef USEREFLECTION\n"
1394 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1395 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1396 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1397 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1398 " // FIXME temporary hack to detect the case that the reflection\n"
1399 " // gets blackened at edges due to leaving the area that contains actual\n"
1401 " // Remove this 'ack once we have a better way to stop this thing from\n"
1403 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1404 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1405 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1406 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1407 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1408 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1411 " gl_FragColor = vec4(color);\n"
1413 "#if showshadowmap\n"
1414 "# ifdef USESHADOWMAPRECT\n"
1415 "# ifdef USESHADOWSAMPLER\n"
1416 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1418 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1421 "# ifdef USESHADOWMAP2D\n"
1422 "# ifdef USESHADOWSAMPLER\n"
1423 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1425 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1429 "# ifdef USESHADOWMAPCUBE\n"
1430 "# ifdef USESHADOWSAMPLER\n"
1431 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1433 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1438 "#endif // !MODE_REFRACTION\n"
1439 "#endif // !MODE_WATER\n"
1441 "#endif // FRAGMENT_SHADER\n"
1443 "#endif // !MODE_GENERIC\n"
1444 "#endif // !MODE_POSTPROCESS\n"
1445 "#endif // !MODE_SHOWDEPTH\n"
1446 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1449 typedef struct shaderpermutationinfo_s
1451 const char *pretext;
1454 shaderpermutationinfo_t;
1456 typedef struct shadermodeinfo_s
1458 const char *vertexfilename;
1459 const char *geometryfilename;
1460 const char *fragmentfilename;
1461 const char *pretext;
1466 typedef enum shaderpermutation_e
1468 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1469 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1470 SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
1471 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1472 SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
1473 SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
1474 SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
1475 SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
1476 SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
1477 SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
1478 SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
1479 SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
1480 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1481 SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1482 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
1483 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1484 SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
1485 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<12, ///< (lightsource) use shadowmap cubemap texture as light filter
1486 SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
1487 SHADERPERMUTATION_SHADOWMAPPCF = 1<<14, //< (lightsource) use percentage closer filtering on shadowmap test results
1488 SHADERPERMUTATION_SHADOWSAMPLER = 1<<15, //< (lightsource) use hardware shadowmap test
1489 SHADERPERMUTATION_LIMIT = 1<<16, ///< size of permutations array
1490 SHADERPERMUTATION_COUNT = 16 ///< size of shaderpermutationinfo array
1492 shaderpermutation_t;
1494 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1495 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1497 {"#define USEDIFFUSE\n", " diffuse"},
1498 {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
1499 {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
1500 {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
1501 {"#define USECUBEFILTER\n", " cubefilter"},
1502 {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
1503 {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
1504 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1505 {"#define USEREFLECTION\n", " reflection"},
1506 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1507 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1508 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1509 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1510 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1511 {"#define USESHADOWMAPPCF\n", " shadowmappcf"},
1512 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1515 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1516 typedef enum shadermode_e
1518 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1519 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1520 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1521 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1522 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1523 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1524 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1525 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1526 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1527 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1528 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1529 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1530 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1535 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1536 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1538 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1539 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1540 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1541 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1542 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1543 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1544 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1545 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1546 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1547 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1548 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1549 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1550 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1553 typedef struct r_glsl_permutation_s
1555 /// indicates if we have tried compiling this permutation already
1557 /// 0 if compilation failed
1559 /// locations of detected uniforms in program object, or -1 if not found
1560 int loc_Texture_First;
1561 int loc_Texture_Second;
1562 int loc_Texture_GammaRamps;
1563 int loc_Texture_Normal;
1564 int loc_Texture_Color;
1565 int loc_Texture_Gloss;
1566 int loc_Texture_Glow;
1567 int loc_Texture_SecondaryNormal;
1568 int loc_Texture_SecondaryColor;
1569 int loc_Texture_SecondaryGloss;
1570 int loc_Texture_SecondaryGlow;
1571 int loc_Texture_Pants;
1572 int loc_Texture_Shirt;
1573 int loc_Texture_FogMask;
1574 int loc_Texture_Lightmap;
1575 int loc_Texture_Deluxemap;
1576 int loc_Texture_Attenuation;
1577 int loc_Texture_Cube;
1578 int loc_Texture_Refraction;
1579 int loc_Texture_Reflection;
1580 int loc_Texture_ShadowMapRect;
1581 int loc_Texture_ShadowMapCube;
1582 int loc_Texture_ShadowMap2D;
1583 int loc_Texture_CubeProjection;
1585 int loc_LightPosition;
1586 int loc_EyePosition;
1587 int loc_Color_Pants;
1588 int loc_Color_Shirt;
1589 int loc_FogRangeRecip;
1590 int loc_AmbientScale;
1591 int loc_DiffuseScale;
1592 int loc_SpecularScale;
1593 int loc_SpecularPower;
1595 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1596 int loc_OffsetMapping_Scale;
1598 int loc_AmbientColor;
1599 int loc_DiffuseColor;
1600 int loc_SpecularColor;
1602 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1603 int loc_GammaCoeff; ///< 1 / gamma
1604 int loc_DistortScaleRefractReflect;
1605 int loc_ScreenScaleRefractReflect;
1606 int loc_ScreenCenterRefractReflect;
1607 int loc_RefractColor;
1608 int loc_ReflectColor;
1609 int loc_ReflectFactor;
1610 int loc_ReflectOffset;
1618 int loc_ShadowMap_TextureScale;
1619 int loc_ShadowMap_Parameters;
1621 r_glsl_permutation_t;
1623 /// information about each possible shader permutation
1624 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1625 /// currently selected permutation
1626 r_glsl_permutation_t *r_glsl_permutation;
1628 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1631 if (!filename || !filename[0])
1633 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1636 if (printfromdisknotice)
1637 Con_DPrint("from disk... ");
1638 return shaderstring;
1640 else if (!strcmp(filename, "glsl/default.glsl"))
1642 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1643 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1645 return shaderstring;
1648 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1651 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1652 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1653 int vertstrings_count = 0;
1654 int geomstrings_count = 0;
1655 int fragstrings_count = 0;
1656 char *vertexstring, *geometrystring, *fragmentstring;
1657 const char *vertstrings_list[32+3];
1658 const char *geomstrings_list[32+3];
1659 const char *fragstrings_list[32+3];
1660 char permutationname[256];
1667 permutationname[0] = 0;
1668 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1669 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1670 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1672 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1674 // the first pretext is which type of shader to compile as
1675 // (later these will all be bound together as a program object)
1676 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1677 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1678 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1680 // the second pretext is the mode (for example a light source)
1681 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1682 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1683 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1684 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1686 // now add all the permutation pretexts
1687 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1689 if (permutation & (1<<i))
1691 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1692 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1693 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1694 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1698 // keep line numbers correct
1699 vertstrings_list[vertstrings_count++] = "\n";
1700 geomstrings_list[geomstrings_count++] = "\n";
1701 fragstrings_list[fragstrings_count++] = "\n";
1705 // now append the shader text itself
1706 vertstrings_list[vertstrings_count++] = vertexstring;
1707 geomstrings_list[geomstrings_count++] = geometrystring;
1708 fragstrings_list[fragstrings_count++] = fragmentstring;
1710 // if any sources were NULL, clear the respective list
1712 vertstrings_count = 0;
1713 if (!geometrystring)
1714 geomstrings_count = 0;
1715 if (!fragmentstring)
1716 fragstrings_count = 0;
1718 // compile the shader program
1719 if (vertstrings_count + geomstrings_count + fragstrings_count)
1720 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1724 qglUseProgramObjectARB(p->program);CHECKGLERROR
1725 // look up all the uniform variable names we care about, so we don't
1726 // have to look them up every time we set them
1727 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1728 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1729 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1730 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1731 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1732 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1733 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1734 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1735 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1736 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1737 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1738 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1739 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1740 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1741 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1742 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1743 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1744 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1745 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1746 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1747 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1748 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1749 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1750 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1751 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1752 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1753 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1754 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1755 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1756 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1757 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1758 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1759 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1760 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1761 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1762 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1763 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1764 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1765 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1766 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1767 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1768 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1769 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1770 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1771 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1772 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1773 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1774 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1775 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1776 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1777 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1778 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1779 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1780 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1781 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1782 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1783 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1784 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1785 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1786 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1787 // initialize the samplers to refer to the texture units we use
1788 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1789 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1790 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1791 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1792 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1793 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1794 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1795 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1796 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1797 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1798 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1799 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1800 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1801 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1802 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1803 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1804 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1805 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1806 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1807 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1808 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1809 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1810 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1811 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1813 if (developer.integer)
1814 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1817 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1821 Mem_Free(vertexstring);
1823 Mem_Free(geometrystring);
1825 Mem_Free(fragmentstring);
1828 void R_GLSL_Restart_f(void)
1831 unsigned int permutation;
1832 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1833 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1834 if (r_glsl_permutations[mode][permutation].program)
1835 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1836 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1839 void R_GLSL_DumpShader_f(void)
1843 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1846 Con_Printf("failed to write to glsl/default.glsl\n");
1850 FS_Print(file, "/* The engine may define the following macros:\n");
1851 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1852 for (i = 0;i < SHADERMODE_COUNT;i++)
1853 FS_Print(file, shadermodeinfo[i].pretext);
1854 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1855 FS_Print(file, shaderpermutationinfo[i].pretext);
1856 FS_Print(file, "*/\n");
1857 FS_Print(file, builtinshaderstring);
1860 Con_Printf("glsl/default.glsl written\n");
1863 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1865 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1866 if (r_glsl_permutation != perm)
1868 r_glsl_permutation = perm;
1869 if (!r_glsl_permutation->program)
1871 if (!r_glsl_permutation->compiled)
1872 R_GLSL_CompilePermutation(mode, permutation);
1873 if (!r_glsl_permutation->program)
1875 // remove features until we find a valid permutation
1877 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1879 // reduce i more quickly whenever it would not remove any bits
1880 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1881 if (!(permutation & j))
1884 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1885 if (!r_glsl_permutation->compiled)
1886 R_GLSL_CompilePermutation(mode, permutation);
1887 if (r_glsl_permutation->program)
1890 if (i >= SHADERPERMUTATION_COUNT)
1892 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");
1893 Cvar_SetValueQuick(&r_glsl, 0);
1894 R_GLSL_Restart_f(); // unload shaders
1895 return; // no bit left to clear
1900 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1904 void R_SetupGenericShader(qboolean usetexture)
1906 if (gl_support_fragment_shader)
1908 if (r_glsl.integer && r_glsl_usegeneric.integer)
1909 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1910 else if (r_glsl_permutation)
1912 r_glsl_permutation = NULL;
1913 qglUseProgramObjectARB(0);CHECKGLERROR
1918 void R_SetupGenericTwoTextureShader(int texturemode)
1920 if (gl_support_fragment_shader)
1922 if (r_glsl.integer && r_glsl_usegeneric.integer)
1923 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))));
1924 else if (r_glsl_permutation)
1926 r_glsl_permutation = NULL;
1927 qglUseProgramObjectARB(0);CHECKGLERROR
1930 if (!r_glsl_permutation)
1932 if (texturemode == GL_DECAL && gl_combine.integer)
1933 texturemode = GL_INTERPOLATE_ARB;
1934 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1938 void R_SetupDepthOrShadowShader(void)
1940 if (gl_support_fragment_shader)
1942 if (r_glsl.integer && r_glsl_usegeneric.integer)
1943 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1944 else if (r_glsl_permutation)
1946 r_glsl_permutation = NULL;
1947 qglUseProgramObjectARB(0);CHECKGLERROR
1952 void R_SetupShowDepthShader(void)
1954 if (gl_support_fragment_shader)
1956 if (r_glsl.integer && r_glsl_usegeneric.integer)
1957 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
1958 else if (r_glsl_permutation)
1960 r_glsl_permutation = NULL;
1961 qglUseProgramObjectARB(0);CHECKGLERROR
1966 extern rtexture_t *r_shadow_attenuationgradienttexture;
1967 extern rtexture_t *r_shadow_attenuation2dtexture;
1968 extern rtexture_t *r_shadow_attenuation3dtexture;
1969 extern qboolean r_shadow_usingshadowmaprect;
1970 extern qboolean r_shadow_usingshadowmapcube;
1971 extern qboolean r_shadow_usingshadowmap2d;
1972 extern float r_shadow_shadowmap_texturescale[4];
1973 extern float r_shadow_shadowmap_parameters[4];
1974 extern int r_shadow_shadowmode;
1975 extern int r_shadow_shadowmapfilter;
1976 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1978 // select a permutation of the lighting shader appropriate to this
1979 // combination of texture, entity, light source, and fogging, only use the
1980 // minimum features necessary to avoid wasting rendering time in the
1981 // fragment shader on features that are not being used
1982 unsigned int permutation = 0;
1983 unsigned int mode = 0;
1984 // TODO: implement geometry-shader based shadow volumes someday
1985 if (r_glsl_offsetmapping.integer)
1987 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1988 if (r_glsl_offsetmapping_reliefmapping.integer)
1989 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1991 if (rsurfacepass == RSURFPASS_BACKGROUND)
1993 // distorted background
1994 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1995 mode = SHADERMODE_WATER;
1997 mode = SHADERMODE_REFRACTION;
1999 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2002 mode = SHADERMODE_LIGHTSOURCE;
2003 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2004 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2005 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2006 permutation |= SHADERPERMUTATION_CUBEFILTER;
2007 if (diffusescale > 0)
2008 permutation |= SHADERPERMUTATION_DIFFUSE;
2009 if (specularscale > 0)
2010 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2011 if (r_refdef.fogenabled)
2012 permutation |= SHADERPERMUTATION_FOG;
2013 if (rsurface.texture->colormapping)
2014 permutation |= SHADERPERMUTATION_COLORMAPPING;
2015 if (r_shadow_usingshadowmaprect)
2016 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2017 if (r_shadow_usingshadowmapcube)
2018 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2019 if (r_shadow_usingshadowmap2d)
2020 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2021 if (r_shadow_shadowmapfilter == 3)
2022 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2023 else if (r_shadow_shadowmapfilter == 2)
2024 permutation |= SHADERPERMUTATION_SHADOWMAPPCF | SHADERPERMUTATION_SHADOWSAMPLER;
2025 else if (r_shadow_shadowmapfilter == 1)
2026 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2028 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2030 // unshaded geometry (fullbright or ambient model lighting)
2031 mode = SHADERMODE_FLATCOLOR;
2032 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2033 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2034 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2035 permutation |= SHADERPERMUTATION_GLOW;
2036 if (r_refdef.fogenabled)
2037 permutation |= SHADERPERMUTATION_FOG;
2038 if (rsurface.texture->colormapping)
2039 permutation |= SHADERPERMUTATION_COLORMAPPING;
2040 if (r_glsl_offsetmapping.integer)
2042 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2043 if (r_glsl_offsetmapping_reliefmapping.integer)
2044 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2046 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2047 permutation |= SHADERPERMUTATION_REFLECTION;
2049 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2051 // directional model lighting
2052 mode = SHADERMODE_LIGHTDIRECTION;
2053 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2054 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2055 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2056 permutation |= SHADERPERMUTATION_GLOW;
2057 permutation |= SHADERPERMUTATION_DIFFUSE;
2058 if (specularscale > 0)
2059 permutation |= SHADERPERMUTATION_SPECULAR;
2060 if (r_refdef.fogenabled)
2061 permutation |= SHADERPERMUTATION_FOG;
2062 if (rsurface.texture->colormapping)
2063 permutation |= SHADERPERMUTATION_COLORMAPPING;
2064 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2065 permutation |= SHADERPERMUTATION_REFLECTION;
2067 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2069 // ambient model lighting
2070 mode = SHADERMODE_LIGHTDIRECTION;
2071 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2072 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2073 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2074 permutation |= SHADERPERMUTATION_GLOW;
2075 if (r_refdef.fogenabled)
2076 permutation |= SHADERPERMUTATION_FOG;
2077 if (rsurface.texture->colormapping)
2078 permutation |= SHADERPERMUTATION_COLORMAPPING;
2079 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2080 permutation |= SHADERPERMUTATION_REFLECTION;
2085 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2087 // deluxemapping (light direction texture)
2088 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2089 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2091 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2092 permutation |= SHADERPERMUTATION_DIFFUSE;
2093 if (specularscale > 0)
2094 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2096 else if (r_glsl_deluxemapping.integer >= 2)
2098 // fake deluxemapping (uniform light direction in tangentspace)
2099 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2100 permutation |= SHADERPERMUTATION_DIFFUSE;
2101 if (specularscale > 0)
2102 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2104 else if (rsurface.uselightmaptexture)
2106 // ordinary lightmapping (q1bsp, q3bsp)
2107 mode = SHADERMODE_LIGHTMAP;
2111 // ordinary vertex coloring (q3bsp)
2112 mode = SHADERMODE_VERTEXCOLOR;
2114 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2115 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2116 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2117 permutation |= SHADERPERMUTATION_GLOW;
2118 if (r_refdef.fogenabled)
2119 permutation |= SHADERPERMUTATION_FOG;
2120 if (rsurface.texture->colormapping)
2121 permutation |= SHADERPERMUTATION_COLORMAPPING;
2122 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2123 permutation |= SHADERPERMUTATION_REFLECTION;
2125 if(permutation & SHADERPERMUTATION_SPECULAR)
2126 if(r_shadow_glossexact.integer)
2127 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2128 R_SetupShader_SetPermutation(mode, permutation);
2129 if (mode == SHADERMODE_LIGHTSOURCE)
2131 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2132 if (permutation & SHADERPERMUTATION_DIFFUSE)
2134 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2135 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2136 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2137 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2141 // ambient only is simpler
2142 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]);
2143 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2144 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2145 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2147 // additive passes are only darkened by fog, not tinted
2148 if (r_glsl_permutation->loc_FogColor >= 0)
2149 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2150 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]);
2151 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]);
2155 if (mode == SHADERMODE_LIGHTDIRECTION)
2157 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);
2158 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);
2159 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);
2160 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]);
2164 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2165 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2166 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2168 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]);
2169 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
2170 // additive passes are only darkened by fog, not tinted
2171 if (r_glsl_permutation->loc_FogColor >= 0)
2173 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2174 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2176 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2178 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);
2179 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]);
2180 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]);
2181 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2182 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2183 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2184 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2186 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2187 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
2188 if (r_glsl_permutation->loc_Color_Pants >= 0)
2190 if (rsurface.texture->currentskinframe->pants)
2191 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2193 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2195 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2197 if (rsurface.texture->currentskinframe->shirt)
2198 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2200 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2202 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
2203 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2205 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2209 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2211 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2215 #define SKINFRAME_HASH 1024
2219 int loadsequence; // incremented each level change
2220 memexpandablearray_t array;
2221 skinframe_t *hash[SKINFRAME_HASH];
2224 r_skinframe_t r_skinframe;
2226 void R_SkinFrame_PrepareForPurge(void)
2228 r_skinframe.loadsequence++;
2229 // wrap it without hitting zero
2230 if (r_skinframe.loadsequence >= 200)
2231 r_skinframe.loadsequence = 1;
2234 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2238 // mark the skinframe as used for the purging code
2239 skinframe->loadsequence = r_skinframe.loadsequence;
2242 void R_SkinFrame_Purge(void)
2246 for (i = 0;i < SKINFRAME_HASH;i++)
2248 for (s = r_skinframe.hash[i];s;s = s->next)
2250 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2252 if (s->merged == s->base)
2254 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2255 R_PurgeTexture(s->stain );s->stain = NULL;
2256 R_PurgeTexture(s->merged);s->merged = NULL;
2257 R_PurgeTexture(s->base );s->base = NULL;
2258 R_PurgeTexture(s->pants );s->pants = NULL;
2259 R_PurgeTexture(s->shirt );s->shirt = NULL;
2260 R_PurgeTexture(s->nmap );s->nmap = NULL;
2261 R_PurgeTexture(s->gloss );s->gloss = NULL;
2262 R_PurgeTexture(s->glow );s->glow = NULL;
2263 R_PurgeTexture(s->fog );s->fog = NULL;
2264 s->loadsequence = 0;
2270 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2272 char basename[MAX_QPATH];
2274 Image_StripImageExtension(name, basename, sizeof(basename));
2276 if( last == NULL ) {
2278 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2279 item = r_skinframe.hash[hashindex];
2284 // linearly search through the hash bucket
2285 for( ; item ; item = item->next ) {
2286 if( !strcmp( item->basename, basename ) ) {
2293 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2297 char basename[MAX_QPATH];
2299 Image_StripImageExtension(name, basename, sizeof(basename));
2301 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2302 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2303 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2307 rtexture_t *dyntexture;
2308 // check whether its a dynamic texture
2309 dyntexture = CL_GetDynTexture( basename );
2310 if (!add && !dyntexture)
2312 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2313 memset(item, 0, sizeof(*item));
2314 strlcpy(item->basename, basename, sizeof(item->basename));
2315 item->base = dyntexture; // either NULL or dyntexture handle
2316 item->textureflags = textureflags;
2317 item->comparewidth = comparewidth;
2318 item->compareheight = compareheight;
2319 item->comparecrc = comparecrc;
2320 item->next = r_skinframe.hash[hashindex];
2321 r_skinframe.hash[hashindex] = item;
2323 else if( item->base == NULL )
2325 rtexture_t *dyntexture;
2326 // check whether its a dynamic texture
2327 // 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]
2328 dyntexture = CL_GetDynTexture( basename );
2329 item->base = dyntexture; // either NULL or dyntexture handle
2332 R_SkinFrame_MarkUsed(item);
2336 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2338 unsigned long long avgcolor[5], wsum; \
2346 for(pix = 0; pix < cnt; ++pix) \
2349 for(comp = 0; comp < 3; ++comp) \
2351 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2354 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2356 for(comp = 0; comp < 3; ++comp) \
2357 avgcolor[comp] += getpixel * w; \
2360 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2361 avgcolor[4] += getpixel; \
2363 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2365 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2366 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2367 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2368 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2371 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2373 // FIXME: it should be possible to disable loading various layers using
2374 // cvars, to prevent wasted loading time and memory usage if the user does
2376 qboolean loadnormalmap = true;
2377 qboolean loadgloss = true;
2378 qboolean loadpantsandshirt = true;
2379 qboolean loadglow = true;
2381 unsigned char *pixels;
2382 unsigned char *bumppixels;
2383 unsigned char *basepixels = NULL;
2384 int basepixels_width;
2385 int basepixels_height;
2386 skinframe_t *skinframe;
2390 if (cls.state == ca_dedicated)
2393 // return an existing skinframe if already loaded
2394 // if loading of the first image fails, don't make a new skinframe as it
2395 // would cause all future lookups of this to be missing
2396 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2397 if (skinframe && skinframe->base)
2400 basepixels = loadimagepixelsbgra(name, complain, true);
2401 if (basepixels == NULL)
2404 if (developer_loading.integer)
2405 Con_Printf("loading skin \"%s\"\n", name);
2407 // we've got some pixels to store, so really allocate this new texture now
2409 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2410 skinframe->stain = NULL;
2411 skinframe->merged = NULL;
2412 skinframe->base = r_texture_notexture;
2413 skinframe->pants = NULL;
2414 skinframe->shirt = NULL;
2415 skinframe->nmap = r_texture_blanknormalmap;
2416 skinframe->gloss = NULL;
2417 skinframe->glow = NULL;
2418 skinframe->fog = NULL;
2420 basepixels_width = image_width;
2421 basepixels_height = image_height;
2422 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);
2424 if (textureflags & TEXF_ALPHA)
2426 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2427 if (basepixels[j] < 255)
2429 if (j < basepixels_width * basepixels_height * 4)
2431 // has transparent pixels
2433 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2434 for (j = 0;j < image_width * image_height * 4;j += 4)
2439 pixels[j+3] = basepixels[j+3];
2441 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);
2446 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2447 //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]);
2449 // _norm is the name used by tenebrae and has been adopted as standard
2452 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2454 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);
2458 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2460 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2461 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2462 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);
2464 Mem_Free(bumppixels);
2466 else if (r_shadow_bumpscale_basetexture.value > 0)
2468 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2469 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2470 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);
2474 // _luma is supported for tenebrae compatibility
2475 // (I think it's a very stupid name, but oh well)
2476 // _glow is the preferred name
2477 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;}
2478 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;}
2479 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;}
2480 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;}
2483 Mem_Free(basepixels);
2488 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2491 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2494 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)
2499 for (i = 0;i < width*height;i++)
2500 if (((unsigned char *)&palette[in[i]])[3] > 0)
2502 if (i == width*height)
2505 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2508 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2509 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2512 unsigned char *temp1, *temp2;
2513 skinframe_t *skinframe;
2515 if (cls.state == ca_dedicated)
2518 // if already loaded just return it, otherwise make a new skinframe
2519 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2520 if (skinframe && skinframe->base)
2523 skinframe->stain = NULL;
2524 skinframe->merged = NULL;
2525 skinframe->base = r_texture_notexture;
2526 skinframe->pants = NULL;
2527 skinframe->shirt = NULL;
2528 skinframe->nmap = r_texture_blanknormalmap;
2529 skinframe->gloss = NULL;
2530 skinframe->glow = NULL;
2531 skinframe->fog = NULL;
2533 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2537 if (developer_loading.integer)
2538 Con_Printf("loading 32bit skin \"%s\"\n", name);
2540 if (r_shadow_bumpscale_basetexture.value > 0)
2542 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2543 temp2 = temp1 + width * height * 4;
2544 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2545 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2548 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2549 if (textureflags & TEXF_ALPHA)
2551 for (i = 3;i < width * height * 4;i += 4)
2552 if (skindata[i] < 255)
2554 if (i < width * height * 4)
2556 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2557 memcpy(fogpixels, skindata, width * height * 4);
2558 for (i = 0;i < width * height * 4;i += 4)
2559 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2560 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2561 Mem_Free(fogpixels);
2565 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2566 //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]);
2571 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2574 unsigned char *temp1, *temp2;
2575 unsigned int *palette;
2576 skinframe_t *skinframe;
2578 if (cls.state == ca_dedicated)
2581 // if already loaded just return it, otherwise make a new skinframe
2582 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2583 if (skinframe && skinframe->base)
2586 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2588 skinframe->stain = NULL;
2589 skinframe->merged = NULL;
2590 skinframe->base = r_texture_notexture;
2591 skinframe->pants = NULL;
2592 skinframe->shirt = NULL;
2593 skinframe->nmap = r_texture_blanknormalmap;
2594 skinframe->gloss = NULL;
2595 skinframe->glow = NULL;
2596 skinframe->fog = NULL;
2598 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2602 if (developer_loading.integer)
2603 Con_Printf("loading quake skin \"%s\"\n", name);
2605 if (r_shadow_bumpscale_basetexture.value > 0)
2607 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2608 temp2 = temp1 + width * height * 4;
2609 // use either a custom palette or the quake palette
2610 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2611 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2612 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2615 // use either a custom palette, or the quake palette
2616 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2617 if (loadglowtexture)
2618 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2619 if (loadpantsandshirt)
2621 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2622 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2624 if (skinframe->pants || skinframe->shirt)
2625 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
2626 if (textureflags & TEXF_ALPHA)
2628 for (i = 0;i < width * height;i++)
2629 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2631 if (i < width * height)
2632 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2635 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2636 //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]);
2641 skinframe_t *R_SkinFrame_LoadMissing(void)
2643 skinframe_t *skinframe;
2645 if (cls.state == ca_dedicated)
2648 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2649 skinframe->stain = NULL;
2650 skinframe->merged = NULL;
2651 skinframe->base = r_texture_notexture;
2652 skinframe->pants = NULL;
2653 skinframe->shirt = NULL;
2654 skinframe->nmap = r_texture_blanknormalmap;
2655 skinframe->gloss = NULL;
2656 skinframe->glow = NULL;
2657 skinframe->fog = NULL;
2659 skinframe->avgcolor[0] = rand() / RAND_MAX;
2660 skinframe->avgcolor[1] = rand() / RAND_MAX;
2661 skinframe->avgcolor[2] = rand() / RAND_MAX;
2662 skinframe->avgcolor[3] = 1;
2667 void gl_main_start(void)
2671 memset(r_queries, 0, sizeof(r_queries));
2673 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2674 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2676 // set up r_skinframe loading system for textures
2677 memset(&r_skinframe, 0, sizeof(r_skinframe));
2678 r_skinframe.loadsequence = 1;
2679 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2681 r_main_texturepool = R_AllocTexturePool();
2682 R_BuildBlankTextures();
2684 if (gl_texturecubemap)
2687 R_BuildNormalizationCube();
2689 r_texture_fogattenuation = NULL;
2690 r_texture_gammaramps = NULL;
2691 //r_texture_fogintensity = NULL;
2692 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2693 memset(&r_waterstate, 0, sizeof(r_waterstate));
2694 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2695 memset(&r_svbsp, 0, sizeof (r_svbsp));
2697 r_refdef.fogmasktable_density = 0;
2700 extern rtexture_t *loadingscreentexture;
2701 void gl_main_shutdown(void)
2704 qglDeleteQueriesARB(r_maxqueries, r_queries);
2708 memset(r_queries, 0, sizeof(r_queries));
2710 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2711 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2713 // clear out the r_skinframe state
2714 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2715 memset(&r_skinframe, 0, sizeof(r_skinframe));
2718 Mem_Free(r_svbsp.nodes);
2719 memset(&r_svbsp, 0, sizeof (r_svbsp));
2720 R_FreeTexturePool(&r_main_texturepool);
2721 loadingscreentexture = NULL;
2722 r_texture_blanknormalmap = NULL;
2723 r_texture_white = NULL;
2724 r_texture_grey128 = NULL;
2725 r_texture_black = NULL;
2726 r_texture_whitecube = NULL;
2727 r_texture_normalizationcube = NULL;
2728 r_texture_fogattenuation = NULL;
2729 r_texture_gammaramps = NULL;
2730 //r_texture_fogintensity = NULL;
2731 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2732 memset(&r_waterstate, 0, sizeof(r_waterstate));
2736 extern void CL_ParseEntityLump(char *entitystring);
2737 void gl_main_newmap(void)
2739 // FIXME: move this code to client
2741 char *entities, entname[MAX_QPATH];
2744 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2745 l = (int)strlen(entname) - 4;
2746 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2748 memcpy(entname + l, ".ent", 5);
2749 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2751 CL_ParseEntityLump(entities);
2756 if (cl.worldmodel->brush.entities)
2757 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2761 void GL_Main_Init(void)
2763 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2765 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2766 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2767 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2768 if (gamemode == GAME_NEHAHRA)
2770 Cvar_RegisterVariable (&gl_fogenable);
2771 Cvar_RegisterVariable (&gl_fogdensity);
2772 Cvar_RegisterVariable (&gl_fogred);
2773 Cvar_RegisterVariable (&gl_foggreen);
2774 Cvar_RegisterVariable (&gl_fogblue);
2775 Cvar_RegisterVariable (&gl_fogstart);
2776 Cvar_RegisterVariable (&gl_fogend);
2777 Cvar_RegisterVariable (&gl_skyclip);
2779 Cvar_RegisterVariable(&r_motionblur);
2780 Cvar_RegisterVariable(&r_motionblur_maxblur);
2781 Cvar_RegisterVariable(&r_motionblur_bmin);
2782 Cvar_RegisterVariable(&r_motionblur_vmin);
2783 Cvar_RegisterVariable(&r_motionblur_vmax);
2784 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2785 Cvar_RegisterVariable(&r_motionblur_randomize);
2786 Cvar_RegisterVariable(&r_damageblur);
2787 Cvar_RegisterVariable(&r_animcache);
2788 Cvar_RegisterVariable(&r_depthfirst);
2789 Cvar_RegisterVariable(&r_useinfinitefarclip);
2790 Cvar_RegisterVariable(&r_nearclip);
2791 Cvar_RegisterVariable(&r_showbboxes);
2792 Cvar_RegisterVariable(&r_showsurfaces);
2793 Cvar_RegisterVariable(&r_showtris);
2794 Cvar_RegisterVariable(&r_shownormals);
2795 Cvar_RegisterVariable(&r_showlighting);
2796 Cvar_RegisterVariable(&r_showshadowvolumes);
2797 Cvar_RegisterVariable(&r_showcollisionbrushes);
2798 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2799 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2800 Cvar_RegisterVariable(&r_showdisabledepthtest);
2801 Cvar_RegisterVariable(&r_drawportals);
2802 Cvar_RegisterVariable(&r_drawentities);
2803 Cvar_RegisterVariable(&r_cullentities_trace);
2804 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2805 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2806 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2807 Cvar_RegisterVariable(&r_drawviewmodel);
2808 Cvar_RegisterVariable(&r_speeds);
2809 Cvar_RegisterVariable(&r_fullbrights);
2810 Cvar_RegisterVariable(&r_wateralpha);
2811 Cvar_RegisterVariable(&r_dynamic);
2812 Cvar_RegisterVariable(&r_fullbright);
2813 Cvar_RegisterVariable(&r_shadows);
2814 Cvar_RegisterVariable(&r_shadows_darken);
2815 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
2816 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2817 Cvar_RegisterVariable(&r_shadows_throwdistance);
2818 Cvar_RegisterVariable(&r_shadows_throwdirection);
2819 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2820 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2821 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2822 Cvar_RegisterVariable(&r_fog_exp2);
2823 Cvar_RegisterVariable(&r_drawfog);
2824 Cvar_RegisterVariable(&r_textureunits);
2825 Cvar_RegisterVariable(&r_glsl);
2826 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2827 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2828 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2829 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2830 Cvar_RegisterVariable(&r_glsl_postprocess);
2831 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2832 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2833 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2834 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2835 Cvar_RegisterVariable(&r_glsl_usegeneric);
2836 Cvar_RegisterVariable(&r_water);
2837 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2838 Cvar_RegisterVariable(&r_water_clippingplanebias);
2839 Cvar_RegisterVariable(&r_water_refractdistort);
2840 Cvar_RegisterVariable(&r_water_reflectdistort);
2841 Cvar_RegisterVariable(&r_lerpsprites);
2842 Cvar_RegisterVariable(&r_lerpmodels);
2843 Cvar_RegisterVariable(&r_lerplightstyles);
2844 Cvar_RegisterVariable(&r_waterscroll);
2845 Cvar_RegisterVariable(&r_bloom);
2846 Cvar_RegisterVariable(&r_bloom_colorscale);
2847 Cvar_RegisterVariable(&r_bloom_brighten);
2848 Cvar_RegisterVariable(&r_bloom_blur);
2849 Cvar_RegisterVariable(&r_bloom_resolution);
2850 Cvar_RegisterVariable(&r_bloom_colorexponent);
2851 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2852 Cvar_RegisterVariable(&r_hdr);
2853 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2854 Cvar_RegisterVariable(&r_hdr_glowintensity);
2855 Cvar_RegisterVariable(&r_hdr_range);
2856 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2857 Cvar_RegisterVariable(&developer_texturelogging);
2858 Cvar_RegisterVariable(&gl_lightmaps);
2859 Cvar_RegisterVariable(&r_test);
2860 Cvar_RegisterVariable(&r_batchmode);
2861 Cvar_RegisterVariable(&r_glsl_saturation);
2862 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2863 Cvar_SetValue("r_fullbrights", 0);
2864 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2866 Cvar_RegisterVariable(&r_track_sprites);
2867 Cvar_RegisterVariable(&r_track_sprites_flags);
2868 Cvar_RegisterVariable(&r_track_sprites_scalew);
2869 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2872 extern void R_Textures_Init(void);
2873 extern void GL_Draw_Init(void);
2874 extern void GL_Main_Init(void);
2875 extern void R_Shadow_Init(void);
2876 extern void R_Sky_Init(void);
2877 extern void GL_Surf_Init(void);
2878 extern void R_Particles_Init(void);
2879 extern void R_Explosion_Init(void);
2880 extern void gl_backend_init(void);
2881 extern void Sbar_Init(void);
2882 extern void R_LightningBeams_Init(void);
2883 extern void Mod_RenderInit(void);
2885 void Render_Init(void)
2897 R_LightningBeams_Init();
2906 extern char *ENGINE_EXTENSIONS;
2909 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2910 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2911 gl_version = (const char *)qglGetString(GL_VERSION);
2912 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2916 if (!gl_platformextensions)
2917 gl_platformextensions = "";
2919 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2920 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2921 Con_Printf("GL_VERSION: %s\n", gl_version);
2922 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2923 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2925 VID_CheckExtensions();
2927 // LordHavoc: report supported extensions
2928 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2930 // clear to black (loading plaque will be seen over this)
2932 qglClearColor(0,0,0,1);CHECKGLERROR
2933 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2936 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2940 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2942 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2945 p = r_refdef.view.frustum + i;
2950 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2954 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2958 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2962 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2966 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2970 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2974 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2978 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2986 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2990 for (i = 0;i < numplanes;i++)
2997 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3001 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3005 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3009 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3013 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3017 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3021 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3025 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3033 //==================================================================================
3035 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3038 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3039 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3040 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3043 typedef struct r_animcache_entity_s
3050 qboolean wantnormals;
3051 qboolean wanttangents;
3053 r_animcache_entity_t;
3055 typedef struct r_animcache_s
3057 r_animcache_entity_t entity[MAX_EDICTS*2];
3063 static r_animcache_t r_animcachestate;
3065 void R_AnimCache_Free(void)
3068 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3070 r_animcachestate.entity[idx].maxvertices = 0;
3071 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3072 r_animcachestate.entity[idx].vertex3f = NULL;
3073 r_animcachestate.entity[idx].normal3f = NULL;
3074 r_animcachestate.entity[idx].svector3f = NULL;
3075 r_animcachestate.entity[idx].tvector3f = NULL;
3077 r_animcachestate.currentindex = 0;
3078 r_animcachestate.maxindex = 0;
3081 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3085 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3087 if (cache->maxvertices >= numvertices)
3090 // Release existing memory
3091 if (cache->vertex3f)
3092 Mem_Free(cache->vertex3f);
3094 // Pad by 1024 verts
3095 cache->maxvertices = (numvertices + 1023) & ~1023;
3096 arraySize = cache->maxvertices * 3;
3098 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3099 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3100 r_animcachestate.entity[cacheIdx].vertex3f = base;
3101 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3102 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3103 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3105 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3108 void R_AnimCache_NewFrame(void)
3112 if (r_animcache.integer && r_drawentities.integer)
3113 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3114 else if (r_animcachestate.maxindex)
3117 r_animcachestate.currentindex = 0;
3119 for (i = 0;i < r_refdef.scene.numentities;i++)
3120 r_refdef.scene.entities[i]->animcacheindex = -1;
3123 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3125 dp_model_t *model = ent->model;
3126 r_animcache_entity_t *c;
3127 // see if it's already cached this frame
3128 if (ent->animcacheindex >= 0)
3130 // add normals/tangents if needed
3131 c = r_animcachestate.entity + ent->animcacheindex;
3133 wantnormals = false;
3134 if (c->wanttangents)
3135 wanttangents = false;
3136 if (wantnormals || wanttangents)
3137 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3141 // see if this ent is worth caching
3142 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3144 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3146 // assign it a cache entry and make sure the arrays are big enough
3147 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3148 ent->animcacheindex = r_animcachestate.currentindex++;
3149 c = r_animcachestate.entity + ent->animcacheindex;
3150 c->wantnormals = wantnormals;
3151 c->wanttangents = wanttangents;
3152 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3157 void R_AnimCache_CacheVisibleEntities(void)
3160 qboolean wantnormals;
3161 qboolean wanttangents;
3163 if (!r_animcachestate.maxindex)
3166 wantnormals = !r_showsurfaces.integer;
3167 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3169 // TODO: thread this?
3171 for (i = 0;i < r_refdef.scene.numentities;i++)
3173 if (!r_refdef.viewcache.entityvisible[i])
3175 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3179 //==================================================================================
3181 static void R_View_UpdateEntityLighting (void)
3184 entity_render_t *ent;
3185 vec3_t tempdiffusenormal;
3187 for (i = 0;i < r_refdef.scene.numentities;i++)
3189 ent = r_refdef.scene.entities[i];
3191 // skip unseen models
3192 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3196 if (ent->model && ent->model->brush.num_leafs)
3198 // TODO: use modellight for r_ambient settings on world?
3199 VectorSet(ent->modellight_ambient, 0, 0, 0);
3200 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3201 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3205 // fetch the lighting from the worldmodel data
3206 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));
3207 VectorClear(ent->modellight_diffuse);
3208 VectorClear(tempdiffusenormal);
3209 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3212 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3213 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3216 VectorSet(ent->modellight_ambient, 1, 1, 1);
3218 // move the light direction into modelspace coordinates for lighting code
3219 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3220 if(VectorLength2(ent->modellight_lightdir) == 0)
3221 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3222 VectorNormalize(ent->modellight_lightdir);
3226 static void R_View_UpdateEntityVisible (void)
3229 entity_render_t *ent;
3231 if (!r_drawentities.integer)
3234 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3235 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3237 // worldmodel can check visibility
3238 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3239 for (i = 0;i < r_refdef.scene.numentities;i++)
3241 ent = r_refdef.scene.entities[i];
3242 if (!(ent->flags & renderimask))
3243 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)))
3244 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))
3245 r_refdef.viewcache.entityvisible[i] = true;
3247 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3249 for (i = 0;i < r_refdef.scene.numentities;i++)
3251 ent = r_refdef.scene.entities[i];
3252 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
3254 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))
3255 ent->last_trace_visibility = realtime;
3256 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3257 r_refdef.viewcache.entityvisible[i] = 0;
3264 // no worldmodel or it can't check visibility
3265 for (i = 0;i < r_refdef.scene.numentities;i++)
3267 ent = r_refdef.scene.entities[i];
3268 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));
3273 /// only used if skyrendermasked, and normally returns false
3274 int R_DrawBrushModelsSky (void)
3277 entity_render_t *ent;
3279 if (!r_drawentities.integer)
3283 for (i = 0;i < r_refdef.scene.numentities;i++)
3285 if (!r_refdef.viewcache.entityvisible[i])
3287 ent = r_refdef.scene.entities[i];
3288 if (!ent->model || !ent->model->DrawSky)
3290 ent->model->DrawSky(ent);
3296 static void R_DrawNoModel(entity_render_t *ent);
3297 static void R_DrawModels(void)
3300 entity_render_t *ent;
3302 if (!r_drawentities.integer)
3305 for (i = 0;i < r_refdef.scene.numentities;i++)
3307 if (!r_refdef.viewcache.entityvisible[i])
3309 ent = r_refdef.scene.entities[i];
3310 r_refdef.stats.entities++;
3311 if (ent->model && ent->model->Draw != NULL)
3312 ent->model->Draw(ent);
3318 static void R_DrawModelsDepth(void)
3321 entity_render_t *ent;
3323 if (!r_drawentities.integer)
3326 for (i = 0;i < r_refdef.scene.numentities;i++)
3328 if (!r_refdef.viewcache.entityvisible[i])
3330 ent = r_refdef.scene.entities[i];
3331 if (ent->model && ent->model->DrawDepth != NULL)
3332 ent->model->DrawDepth(ent);
3336 static void R_DrawModelsDebug(void)
3339 entity_render_t *ent;
3341 if (!r_drawentities.integer)
3344 for (i = 0;i < r_refdef.scene.numentities;i++)
3346 if (!r_refdef.viewcache.entityvisible[i])
3348 ent = r_refdef.scene.entities[i];
3349 if (ent->model && ent->model->DrawDebug != NULL)
3350 ent->model->DrawDebug(ent);
3354 static void R_DrawModelsAddWaterPlanes(void)
3357 entity_render_t *ent;
3359 if (!r_drawentities.integer)
3362 for (i = 0;i < r_refdef.scene.numentities;i++)
3364 if (!r_refdef.viewcache.entityvisible[i])
3366 ent = r_refdef.scene.entities[i];
3367 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3368 ent->model->DrawAddWaterPlanes(ent);
3372 static void R_View_SetFrustum(void)
3375 double slopex, slopey;
3376 vec3_t forward, left, up, origin;
3378 // we can't trust r_refdef.view.forward and friends in reflected scenes
3379 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3382 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3383 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3384 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3385 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3386 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3387 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3388 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3389 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3390 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3391 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3392 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3393 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3397 zNear = r_refdef.nearclip;
3398 nudge = 1.0 - 1.0 / (1<<23);
3399 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3400 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3401 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3402 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3403 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3404 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3405 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3406 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3412 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3413 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3414 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3415 r_refdef.view.frustum[0].dist = m[15] - m[12];
3417 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3418 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3419 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3420 r_refdef.view.frustum[1].dist = m[15] + m[12];
3422 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3423 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3424 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3425 r_refdef.view.frustum[2].dist = m[15] - m[13];
3427 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3428 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3429 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3430 r_refdef.view.frustum[3].dist = m[15] + m[13];
3432 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3433 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3434 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3435 r_refdef.view.frustum[4].dist = m[15] - m[14];
3437 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3438 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3439 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3440 r_refdef.view.frustum[5].dist = m[15] + m[14];
3443 if (r_refdef.view.useperspective)
3445 slopex = 1.0 / r_refdef.view.frustum_x;
3446 slopey = 1.0 / r_refdef.view.frustum_y;
3447 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3448 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3449 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3450 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3451 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3453 // Leaving those out was a mistake, those were in the old code, and they
3454 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3455 // I couldn't reproduce it after adding those normalizations. --blub
3456 VectorNormalize(r_refdef.view.frustum[0].normal);
3457 VectorNormalize(r_refdef.view.frustum[1].normal);
3458 VectorNormalize(r_refdef.view.frustum[2].normal);
3459 VectorNormalize(r_refdef.view.frustum[3].normal);
3461 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3462 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]);
3463 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]);
3464 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]);
3465 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]);
3467 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3468 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3469 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3470 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3471 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3475 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3476 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3477 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3478 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3479 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3480 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3481 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3482 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3483 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3484 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3486 r_refdef.view.numfrustumplanes = 5;
3488 if (r_refdef.view.useclipplane)
3490 r_refdef.view.numfrustumplanes = 6;
3491 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3494 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3495 PlaneClassify(r_refdef.view.frustum + i);
3497 // LordHavoc: note to all quake engine coders, Quake had a special case
3498 // for 90 degrees which assumed a square view (wrong), so I removed it,
3499 // Quake2 has it disabled as well.
3501 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3502 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3503 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3504 //PlaneClassify(&frustum[0]);
3506 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3507 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3508 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3509 //PlaneClassify(&frustum[1]);
3511 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3512 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3513 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3514 //PlaneClassify(&frustum[2]);
3516 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3517 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3518 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3519 //PlaneClassify(&frustum[3]);
3522 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3523 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3524 //PlaneClassify(&frustum[4]);
3527 void R_View_Update(void)
3529 R_View_SetFrustum();
3530 R_View_WorldVisibility(r_refdef.view.useclipplane);
3531 R_View_UpdateEntityVisible();
3532 R_View_UpdateEntityLighting();
3535 void R_SetupView(qboolean allowwaterclippingplane)
3537 const double *customclipplane = NULL;
3539 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3541 // LordHavoc: couldn't figure out how to make this approach the
3542 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3543 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3544 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3545 dist = r_refdef.view.clipplane.dist;
3546 plane[0] = r_refdef.view.clipplane.normal[0];
3547 plane[1] = r_refdef.view.clipplane.normal[1];
3548 plane[2] = r_refdef.view.clipplane.normal[2];
3550 customclipplane = plane;
3553 if (!r_refdef.view.useperspective)
3554 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);
3555 else if (gl_stencil && r_useinfinitefarclip.integer)
3556 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);
3558 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);
3559 R_SetViewport(&r_refdef.view.viewport);
3562 void R_ResetViewRendering2D(void)
3564 r_viewport_t viewport;
3567 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3568 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);
3569 R_SetViewport(&viewport);
3570 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3571 GL_Color(1, 1, 1, 1);
3572 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3573 GL_BlendFunc(GL_ONE, GL_ZERO);
3574 GL_AlphaTest(false);
3575 GL_ScissorTest(false);
3576 GL_DepthMask(false);
3577 GL_DepthRange(0, 1);
3578 GL_DepthTest(false);
3579 R_Mesh_Matrix(&identitymatrix);
3580 R_Mesh_ResetTextureState();
3581 GL_PolygonOffset(0, 0);
3582 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3583 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3584 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3585 qglStencilMask(~0);CHECKGLERROR
3586 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3587 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3588 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3589 R_SetupGenericShader(true);
3592 void R_ResetViewRendering3D(void)
3597 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3598 GL_Color(1, 1, 1, 1);
3599 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3600 GL_BlendFunc(GL_ONE, GL_ZERO);
3601 GL_AlphaTest(false);
3602 GL_ScissorTest(true);
3604 GL_DepthRange(0, 1);
3606 R_Mesh_Matrix(&identitymatrix);
3607 R_Mesh_ResetTextureState();
3608 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3609 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3610 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3611 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3612 qglStencilMask(~0);CHECKGLERROR
3613 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3614 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3615 GL_CullFace(r_refdef.view.cullface_back);
3616 R_SetupGenericShader(true);
3619 void R_RenderScene(void);
3620 void R_RenderWaterPlanes(void);
3622 static void R_Water_StartFrame(void)
3625 int waterwidth, waterheight, texturewidth, textureheight;
3626 r_waterstate_waterplane_t *p;
3628 // set waterwidth and waterheight to the water resolution that will be
3629 // used (often less than the screen resolution for faster rendering)
3630 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3631 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3633 // calculate desired texture sizes
3634 // can't use water if the card does not support the texture size
3635 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3636 texturewidth = textureheight = waterwidth = waterheight = 0;
3637 else if (gl_support_arb_texture_non_power_of_two)
3639 texturewidth = waterwidth;
3640 textureheight = waterheight;
3644 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3645 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3648 // allocate textures as needed
3649 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3651 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3652 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3654 if (p->texture_refraction)
3655 R_FreeTexture(p->texture_refraction);
3656 p->texture_refraction = NULL;
3657 if (p->texture_reflection)
3658 R_FreeTexture(p->texture_reflection);
3659 p->texture_reflection = NULL;
3661 memset(&r_waterstate, 0, sizeof(r_waterstate));
3662 r_waterstate.waterwidth = waterwidth;
3663 r_waterstate.waterheight = waterheight;
3664 r_waterstate.texturewidth = texturewidth;
3665 r_waterstate.textureheight = textureheight;
3668 // when doing a reduced render (HDR) we want to use a smaller area
3669 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3670 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3672 if (r_waterstate.waterwidth)
3674 r_waterstate.enabled = true;
3676 // set up variables that will be used in shader setup
3677 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3678 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3679 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3680 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3683 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3684 r_waterstate.numwaterplanes = 0;
3687 void R_Water_AddWaterPlane(msurface_t *surface)
3689 int triangleindex, planeindex;
3695 r_waterstate_waterplane_t *p;
3696 texture_t *t = R_GetCurrentTexture(surface->texture);
3697 // just use the first triangle with a valid normal for any decisions
3698 VectorClear(normal);
3699 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3701 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3702 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3703 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3704 TriangleNormal(vert[0], vert[1], vert[2], normal);
3705 if (VectorLength2(normal) >= 0.001)
3709 VectorCopy(normal, plane.normal);
3710 VectorNormalize(plane.normal);
3711 plane.dist = DotProduct(vert[0], plane.normal);
3712 PlaneClassify(&plane);
3713 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3715 // skip backfaces (except if nocullface is set)
3716 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3718 VectorNegate(plane.normal, plane.normal);
3720 PlaneClassify(&plane);
3724 // find a matching plane if there is one
3725 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3726 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3728 if (planeindex >= r_waterstate.maxwaterplanes)
3729 return; // nothing we can do, out of planes
3731 // if this triangle does not fit any known plane rendered this frame, add one
3732 if (planeindex >= r_waterstate.numwaterplanes)
3734 // store the new plane
3735 r_waterstate.numwaterplanes++;
3737 // clear materialflags and pvs
3738 p->materialflags = 0;
3739 p->pvsvalid = false;
3741 // merge this surface's materialflags into the waterplane
3742 p->materialflags |= t->currentmaterialflags;
3743 // merge this surface's PVS into the waterplane
3744 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3745 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3746 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3748 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3753 static void R_Water_ProcessPlanes(void)
3755 r_refdef_view_t originalview;
3756 r_refdef_view_t myview;
3758 r_waterstate_waterplane_t *p;
3760 originalview = r_refdef.view;
3762 // make sure enough textures are allocated
3763 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3765 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3767 if (!p->texture_refraction)
3768 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);
3769 if (!p->texture_refraction)
3773 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3775 if (!p->texture_reflection)
3776 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);
3777 if (!p->texture_reflection)
3783 r_refdef.view = originalview;
3784 r_refdef.view.showdebug = false;
3785 r_refdef.view.width = r_waterstate.waterwidth;
3786 r_refdef.view.height = r_waterstate.waterheight;
3787 r_refdef.view.useclipplane = true;
3788 myview = r_refdef.view;
3789 r_waterstate.renderingscene = true;
3790 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3792 // render the normal view scene and copy into texture
3793 // (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)
3794 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3796 r_refdef.view = myview;
3797 r_refdef.view.clipplane = p->plane;
3798 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3799 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3800 PlaneClassify(&r_refdef.view.clipplane);
3802 R_ResetViewRendering3D();
3803 R_ClearScreen(r_refdef.fogenabled);
3807 // copy view into the screen texture
3808 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3809 GL_ActiveTexture(0);
3811 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
3814 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3816 r_refdef.view = myview;
3817 // render reflected scene and copy into texture
3818 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3819 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3820 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3821 r_refdef.view.clipplane = p->plane;
3822 // reverse the cullface settings for this render
3823 r_refdef.view.cullface_front = GL_FRONT;
3824 r_refdef.view.cullface_back = GL_BACK;
3825 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3827 r_refdef.view.usecustompvs = true;
3829 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3831 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3834 R_ResetViewRendering3D();
3835 R_ClearScreen(r_refdef.fogenabled);
3839 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3840 GL_ActiveTexture(0);
3842 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
3845 r_waterstate.renderingscene = false;
3846 r_refdef.view = originalview;
3847 R_ResetViewRendering3D();
3848 R_ClearScreen(r_refdef.fogenabled);
3852 r_refdef.view = originalview;
3853 r_waterstate.renderingscene = false;
3854 Cvar_SetValueQuick(&r_water, 0);
3855 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3859 void R_Bloom_StartFrame(void)
3861 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3863 // set bloomwidth and bloomheight to the bloom resolution that will be
3864 // used (often less than the screen resolution for faster rendering)
3865 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
3866 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
3867 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
3868 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
3869 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
3871 // calculate desired texture sizes
3872 if (gl_support_arb_texture_non_power_of_two)
3874 screentexturewidth = r_refdef.view.width;
3875 screentextureheight = r_refdef.view.height;
3876 bloomtexturewidth = r_bloomstate.bloomwidth;
3877 bloomtextureheight = r_bloomstate.bloomheight;
3881 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3882 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3883 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3884 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3887 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))
3889 Cvar_SetValueQuick(&r_hdr, 0);
3890 Cvar_SetValueQuick(&r_bloom, 0);
3891 Cvar_SetValueQuick(&r_motionblur, 0);
3892 Cvar_SetValueQuick(&r_damageblur, 0);
3895 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)))
3896 screentexturewidth = screentextureheight = 0;
3897 if (!r_hdr.integer && !r_bloom.integer)
3898 bloomtexturewidth = bloomtextureheight = 0;
3900 // allocate textures as needed
3901 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3903 if (r_bloomstate.texture_screen)
3904 R_FreeTexture(r_bloomstate.texture_screen);
3905 r_bloomstate.texture_screen = NULL;
3906 r_bloomstate.screentexturewidth = screentexturewidth;
3907 r_bloomstate.screentextureheight = screentextureheight;
3908 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3909 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);
3911 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3913 if (r_bloomstate.texture_bloom)
3914 R_FreeTexture(r_bloomstate.texture_bloom);
3915 r_bloomstate.texture_bloom = NULL;
3916 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3917 r_bloomstate.bloomtextureheight = bloomtextureheight;
3918 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3919 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);
3922 // when doing a reduced render (HDR) we want to use a smaller area
3923 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
3924 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3925 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3926 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
3927 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
3929 // set up a texcoord array for the full resolution screen image
3930 // (we have to keep this around to copy back during final render)
3931 r_bloomstate.screentexcoord2f[0] = 0;
3932 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3933 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3934 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3935 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3936 r_bloomstate.screentexcoord2f[5] = 0;
3937 r_bloomstate.screentexcoord2f[6] = 0;
3938 r_bloomstate.screentexcoord2f[7] = 0;
3940 // set up a texcoord array for the reduced resolution bloom image
3941 // (which will be additive blended over the screen image)
3942 r_bloomstate.bloomtexcoord2f[0] = 0;
3943 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3944 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3945 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3946 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3947 r_bloomstate.bloomtexcoord2f[5] = 0;
3948 r_bloomstate.bloomtexcoord2f[6] = 0;
3949 r_bloomstate.bloomtexcoord2f[7] = 0;
3951 if (r_hdr.integer || r_bloom.integer)
3953 r_bloomstate.enabled = true;
3954 r_bloomstate.hdr = r_hdr.integer != 0;
3957 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);
3960 void R_Bloom_CopyBloomTexture(float colorscale)
3962 r_refdef.stats.bloom++;
3964 // scale down screen texture to the bloom texture size
3966 R_SetViewport(&r_bloomstate.viewport);
3967 GL_BlendFunc(GL_ONE, GL_ZERO);
3968 GL_Color(colorscale, colorscale, colorscale, 1);
3969 // TODO: optimize with multitexture or GLSL
3970 R_SetupGenericShader(true);
3971 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3972 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3973 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3974 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3976 // we now have a bloom image in the framebuffer
3977 // copy it into the bloom image texture for later processing
3978 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3979 GL_ActiveTexture(0);
3981 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
3982 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
3985 void R_Bloom_CopyHDRTexture(void)
3987 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3988 GL_ActiveTexture(0);
3990 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
3991 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
3994 void R_Bloom_MakeTexture(void)
3997 float xoffset, yoffset, r, brighten;
3999 r_refdef.stats.bloom++;
4001 R_ResetViewRendering2D();
4002 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4003 R_Mesh_ColorPointer(NULL, 0, 0);
4004 R_SetupGenericShader(true);
4006 // we have a bloom image in the framebuffer
4008 R_SetViewport(&r_bloomstate.viewport);
4010 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4013 r = bound(0, r_bloom_colorexponent.value / x, 1);
4014 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4015 GL_Color(r, r, r, 1);
4016 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4017 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4018 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4019 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4021 // copy the vertically blurred bloom view to a texture
4022 GL_ActiveTexture(0);
4024 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4025 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4028 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4029 brighten = r_bloom_brighten.value;
4031 brighten *= r_hdr_range.value;
4032 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4033 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4035 for (dir = 0;dir < 2;dir++)
4037 // blend on at multiple vertical offsets to achieve a vertical blur
4038 // TODO: do offset blends using GLSL
4039 GL_BlendFunc(GL_ONE, GL_ZERO);
4040 for (x = -range;x <= range;x++)
4042 if (!dir){xoffset = 0;yoffset = x;}
4043 else {xoffset = x;yoffset = 0;}
4044 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4045 yoffset /= (float)r_bloomstate.bloomtextureheight;
4046 // compute a texcoord array with the specified x and y offset
4047 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4048 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4049 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4050 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4051 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4052 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4053 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4054 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4055 // this r value looks like a 'dot' particle, fading sharply to
4056 // black at the edges
4057 // (probably not realistic but looks good enough)
4058 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4059 //r = (dir ? 1.0f : brighten)/(range*2+1);
4060 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
4061 GL_Color(r, r, r, 1);
4062 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4063 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4064 GL_BlendFunc(GL_ONE, GL_ONE);
4067 // copy the vertically blurred bloom view to a texture
4068 GL_ActiveTexture(0);
4070 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4071 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4074 // apply subtract last
4075 // (just like it would be in a GLSL shader)
4076 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4078 GL_BlendFunc(GL_ONE, GL_ZERO);
4079 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4080 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4081 GL_Color(1, 1, 1, 1);
4082 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4083 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4085 GL_BlendFunc(GL_ONE, GL_ONE);
4086 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4087 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4088 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4089 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4090 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4091 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4092 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4094 // copy the darkened bloom view to a texture
4095 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4096 GL_ActiveTexture(0);
4098 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4099 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4103 void R_HDR_RenderBloomTexture(void)
4105 int oldwidth, oldheight;
4106 float oldcolorscale;
4108 oldcolorscale = r_refdef.view.colorscale;
4109 oldwidth = r_refdef.view.width;
4110 oldheight = r_refdef.view.height;
4111 r_refdef.view.width = r_bloomstate.bloomwidth;
4112 r_refdef.view.height = r_bloomstate.bloomheight;
4114 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4115 // TODO: add exposure compensation features
4116 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4118 r_refdef.view.showdebug = false;
4119 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4121 R_ResetViewRendering3D();
4123 R_ClearScreen(r_refdef.fogenabled);
4124 if (r_timereport_active)
4125 R_TimeReport("HDRclear");
4128 if (r_timereport_active)
4129 R_TimeReport("visibility");
4131 // only do secondary renders with HDR if r_hdr is 2 or higher
4132 r_waterstate.numwaterplanes = 0;
4133 if (r_waterstate.enabled && r_hdr.integer >= 2)
4134 R_RenderWaterPlanes();
4136 r_refdef.view.showdebug = true;
4138 r_waterstate.numwaterplanes = 0;
4140 R_ResetViewRendering2D();
4142 R_Bloom_CopyHDRTexture();
4143 R_Bloom_MakeTexture();
4145 // restore the view settings
4146 r_refdef.view.width = oldwidth;
4147 r_refdef.view.height = oldheight;
4148 r_refdef.view.colorscale = oldcolorscale;
4150 R_ResetViewRendering3D();
4152 R_ClearScreen(r_refdef.fogenabled);
4153 if (r_timereport_active)
4154 R_TimeReport("viewclear");
4157 static void R_BlendView(void)
4159 if (r_bloomstate.texture_screen)
4161 // make sure the buffer is available
4162 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4164 R_ResetViewRendering2D();
4165 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4166 R_Mesh_ColorPointer(NULL, 0, 0);
4167 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4168 GL_ActiveTexture(0);CHECKGLERROR
4170 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4172 // declare variables
4174 static float avgspeed;
4176 speed = VectorLength(cl.movement_velocity);
4178 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4179 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4181 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4182 speed = bound(0, speed, 1);
4183 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4185 // calculate values into a standard alpha
4186 cl.motionbluralpha = 1 - exp(-
4188 (r_motionblur.value * speed / 80)
4190 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4193 max(0.0001, cl.time - cl.oldtime) // fps independent
4196 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4197 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4199 if (cl.motionbluralpha > 0)
4201 R_SetupGenericShader(true);
4202 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4203 GL_Color(1, 1, 1, cl.motionbluralpha);
4204 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4205 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4206 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4207 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4211 // copy view into the screen texture
4212 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
4213 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4216 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4218 unsigned int permutation =
4219 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4220 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4221 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4222 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4223 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4225 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4227 // render simple bloom effect
4228 // copy the screen and shrink it and darken it for the bloom process
4229 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4230 // make the bloom texture
4231 R_Bloom_MakeTexture();
4234 R_ResetViewRendering2D();
4235 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4236 R_Mesh_ColorPointer(NULL, 0, 0);
4237 GL_Color(1, 1, 1, 1);
4238 GL_BlendFunc(GL_ONE, GL_ZERO);
4239 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4240 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4241 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4242 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4243 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4244 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4245 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4246 if (r_glsl_permutation->loc_TintColor >= 0)
4247 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4248 if (r_glsl_permutation->loc_ClientTime >= 0)
4249 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4250 if (r_glsl_permutation->loc_PixelSize >= 0)
4251 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4252 if (r_glsl_permutation->loc_UserVec1 >= 0)
4254 float a=0, b=0, c=0, d=0;
4255 #if _MSC_VER >= 1400
4256 #define sscanf sscanf_s
4258 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4259 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4261 if (r_glsl_permutation->loc_UserVec2 >= 0)
4263 float a=0, b=0, c=0, d=0;
4264 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4265 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4267 if (r_glsl_permutation->loc_UserVec3 >= 0)
4269 float a=0, b=0, c=0, d=0;
4270 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4271 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4273 if (r_glsl_permutation->loc_UserVec4 >= 0)
4275 float a=0, b=0, c=0, d=0;
4276 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4277 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4279 if (r_glsl_permutation->loc_Saturation >= 0)
4280 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4281 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4282 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4288 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4290 // render high dynamic range bloom effect
4291 // the bloom texture was made earlier this render, so we just need to
4292 // blend it onto the screen...
4293 R_ResetViewRendering2D();
4294 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4295 R_Mesh_ColorPointer(NULL, 0, 0);
4296 R_SetupGenericShader(true);
4297 GL_Color(1, 1, 1, 1);
4298 GL_BlendFunc(GL_ONE, GL_ONE);
4299 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4300 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4301 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4302 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4304 else if (r_bloomstate.texture_bloom)
4306 // render simple bloom effect
4307 // copy the screen and shrink it and darken it for the bloom process
4308 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4309 // make the bloom texture
4310 R_Bloom_MakeTexture();
4311 // put the original screen image back in place and blend the bloom
4313 R_ResetViewRendering2D();
4314 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4315 R_Mesh_ColorPointer(NULL, 0, 0);
4316 GL_Color(1, 1, 1, 1);
4317 GL_BlendFunc(GL_ONE, GL_ZERO);
4318 // do both in one pass if possible
4319 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4320 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4321 if (r_textureunits.integer >= 2 && gl_combine.integer)
4323 R_SetupGenericTwoTextureShader(GL_ADD);
4324 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4325 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4329 R_SetupGenericShader(true);
4330 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4331 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4332 // now blend on the bloom texture
4333 GL_BlendFunc(GL_ONE, GL_ONE);
4334 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4335 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4337 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4338 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4340 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4342 // apply a color tint to the whole view
4343 R_ResetViewRendering2D();
4344 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4345 R_Mesh_ColorPointer(NULL, 0, 0);
4346 R_SetupGenericShader(false);
4347 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4348 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4349 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4353 matrix4x4_t r_waterscrollmatrix;
4355 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4357 if (r_refdef.fog_density)
4359 r_refdef.fogcolor[0] = r_refdef.fog_red;
4360 r_refdef.fogcolor[1] = r_refdef.fog_green;
4361 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4365 VectorCopy(r_refdef.fogcolor, fogvec);
4366 // color.rgb *= ContrastBoost * SceneBrightness;
4367 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4368 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4369 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4370 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4375 void R_UpdateVariables(void)
4379 r_refdef.scene.ambient = r_ambient.value;
4381 r_refdef.farclip = 4096;
4382 if (r_refdef.scene.worldmodel)
4383 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4384 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4386 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4387 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4388 r_refdef.polygonfactor = 0;
4389 r_refdef.polygonoffset = 0;
4390 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4391 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4393 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4394 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4395 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4396 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4397 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4398 if (r_showsurfaces.integer)
4400 r_refdef.scene.rtworld = false;
4401 r_refdef.scene.rtworldshadows = false;
4402 r_refdef.scene.rtdlight = false;
4403 r_refdef.scene.rtdlightshadows = false;
4404 r_refdef.lightmapintensity = 0;
4407 if (gamemode == GAME_NEHAHRA)
4409 if (gl_fogenable.integer)
4411 r_refdef.oldgl_fogenable = true;
4412 r_refdef.fog_density = gl_fogdensity.value;
4413 r_refdef.fog_red = gl_fogred.value;
4414 r_refdef.fog_green = gl_foggreen.value;
4415 r_refdef.fog_blue = gl_fogblue.value;
4416 r_refdef.fog_alpha = 1;
4417 r_refdef.fog_start = 0;
4418 r_refdef.fog_end = gl_skyclip.value;
4420 else if (r_refdef.oldgl_fogenable)
4422 r_refdef.oldgl_fogenable = false;
4423 r_refdef.fog_density = 0;
4424 r_refdef.fog_red = 0;
4425 r_refdef.fog_green = 0;
4426 r_refdef.fog_blue = 0;
4427 r_refdef.fog_alpha = 0;
4428 r_refdef.fog_start = 0;
4429 r_refdef.fog_end = 0;
4433 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4434 r_refdef.fog_start = max(0, r_refdef.fog_start);
4435 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4437 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4439 if (r_refdef.fog_density && r_drawfog.integer)
4441 r_refdef.fogenabled = true;
4442 // this is the point where the fog reaches 0.9986 alpha, which we
4443 // consider a good enough cutoff point for the texture
4444 // (0.9986 * 256 == 255.6)
4445 if (r_fog_exp2.integer)
4446 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4448 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4449 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4450 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4451 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4452 // fog color was already set
4453 // update the fog texture
4454 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)
4455 R_BuildFogTexture();
4458 r_refdef.fogenabled = false;
4460 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4462 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4464 // build GLSL gamma texture
4465 #define RAMPWIDTH 256
4466 unsigned short ramp[RAMPWIDTH * 3];
4467 unsigned char rampbgr[RAMPWIDTH][4];
4470 r_texture_gammaramps_serial = vid_gammatables_serial;
4472 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4473 for(i = 0; i < RAMPWIDTH; ++i)
4475 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4476 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4477 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4480 if (r_texture_gammaramps)
4482 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4486 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);
4492 // remove GLSL gamma texture
4496 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4497 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4503 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4504 if( scenetype != r_currentscenetype ) {
4505 // store the old scenetype
4506 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4507 r_currentscenetype = scenetype;
4508 // move in the new scene
4509 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4518 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4520 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4521 if( scenetype == r_currentscenetype ) {
4522 return &r_refdef.scene;
4524 return &r_scenes_store[ scenetype ];
4533 void R_RenderView(void)
4535 if (r_timereport_active)
4536 R_TimeReport("start");
4537 r_frame++; // used only by R_GetCurrentTexture
4538 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4540 R_AnimCache_NewFrame();
4542 if (r_refdef.view.isoverlay)
4544 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4545 GL_Clear( GL_DEPTH_BUFFER_BIT );
4546 R_TimeReport("depthclear");
4548 r_refdef.view.showdebug = false;
4550 r_waterstate.enabled = false;
4551 r_waterstate.numwaterplanes = 0;
4559 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4560 return; //Host_Error ("R_RenderView: NULL worldmodel");
4562 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4564 // break apart the view matrix into vectors for various purposes
4565 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4566 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4567 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4568 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4569 // make an inverted copy of the view matrix for tracking sprites
4570 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4572 R_Shadow_UpdateWorldLightSelection();
4574 R_Bloom_StartFrame();
4575 R_Water_StartFrame();
4578 if (r_timereport_active)
4579 R_TimeReport("viewsetup");
4581 R_ResetViewRendering3D();
4583 if (r_refdef.view.clear || r_refdef.fogenabled)
4585 R_ClearScreen(r_refdef.fogenabled);
4586 if (r_timereport_active)
4587 R_TimeReport("viewclear");
4589 r_refdef.view.clear = true;
4591 // this produces a bloom texture to be used in R_BlendView() later
4593 R_HDR_RenderBloomTexture();
4595 r_refdef.view.showdebug = true;
4598 if (r_timereport_active)
4599 R_TimeReport("visibility");
4601 r_waterstate.numwaterplanes = 0;
4602 if (r_waterstate.enabled)
4603 R_RenderWaterPlanes();
4606 r_waterstate.numwaterplanes = 0;
4609 if (r_timereport_active)
4610 R_TimeReport("blendview");
4612 GL_Scissor(0, 0, vid.width, vid.height);
4613 GL_ScissorTest(false);
4617 void R_RenderWaterPlanes(void)
4619 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4621 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4622 if (r_timereport_active)
4623 R_TimeReport("waterworld");
4626 // don't let sound skip if going slow
4627 if (r_refdef.scene.extraupdate)
4630 R_DrawModelsAddWaterPlanes();
4631 if (r_timereport_active)
4632 R_TimeReport("watermodels");
4634 if (r_waterstate.numwaterplanes)
4636 R_Water_ProcessPlanes();
4637 if (r_timereport_active)
4638 R_TimeReport("waterscenes");
4642 extern void R_DrawLightningBeams (void);
4643 extern void VM_CL_AddPolygonsToMeshQueue (void);
4644 extern void R_DrawPortals (void);
4645 extern cvar_t cl_locs_show;
4646 static void R_DrawLocs(void);
4647 static void R_DrawEntityBBoxes(void);
4648 void R_RenderScene(void)
4650 r_refdef.stats.renders++;
4654 // don't let sound skip if going slow
4655 if (r_refdef.scene.extraupdate)
4658 R_MeshQueue_BeginScene();
4662 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);
4664 if (cl.csqc_vidvars.drawworld)
4666 // don't let sound skip if going slow
4667 if (r_refdef.scene.extraupdate)
4670 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4672 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4673 if (r_timereport_active)
4674 R_TimeReport("worldsky");
4677 if (R_DrawBrushModelsSky() && r_timereport_active)
4678 R_TimeReport("bmodelsky");
4681 R_AnimCache_CacheVisibleEntities();
4683 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4685 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4686 if (r_timereport_active)
4687 R_TimeReport("worlddepth");
4689 if (r_depthfirst.integer >= 2)
4691 R_DrawModelsDepth();
4692 if (r_timereport_active)
4693 R_TimeReport("modeldepth");
4696 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4698 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4699 if (r_timereport_active)
4700 R_TimeReport("world");
4703 // don't let sound skip if going slow
4704 if (r_refdef.scene.extraupdate)
4708 if (r_timereport_active)
4709 R_TimeReport("models");
4711 // don't let sound skip if going slow
4712 if (r_refdef.scene.extraupdate)
4715 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4717 R_DrawModelShadows();
4718 R_ResetViewRendering3D();
4719 // don't let sound skip if going slow
4720 if (r_refdef.scene.extraupdate)
4724 R_ShadowVolumeLighting(false);
4725 if (r_timereport_active)
4726 R_TimeReport("rtlights");
4728 // don't let sound skip if going slow
4729 if (r_refdef.scene.extraupdate)
4732 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4734 R_DrawModelShadows();
4735 R_ResetViewRendering3D();
4736 // don't let sound skip if going slow
4737 if (r_refdef.scene.extraupdate)
4741 if (cl.csqc_vidvars.drawworld)
4743 R_DrawLightningBeams();
4744 if (r_timereport_active)
4745 R_TimeReport("lightning");
4748 if (r_timereport_active)
4749 R_TimeReport("decals");
4752 if (r_timereport_active)
4753 R_TimeReport("particles");
4756 if (r_timereport_active)
4757 R_TimeReport("explosions");
4760 R_SetupGenericShader(true);
4761 VM_CL_AddPolygonsToMeshQueue();
4763 if (r_refdef.view.showdebug)
4765 if (cl_locs_show.integer)
4768 if (r_timereport_active)
4769 R_TimeReport("showlocs");
4772 if (r_drawportals.integer)
4775 if (r_timereport_active)
4776 R_TimeReport("portals");
4779 if (r_showbboxes.value > 0)
4781 R_DrawEntityBBoxes();
4782 if (r_timereport_active)
4783 R_TimeReport("bboxes");
4787 R_SetupGenericShader(true);
4788 R_MeshQueue_RenderTransparent();
4789 if (r_timereport_active)
4790 R_TimeReport("drawtrans");
4792 R_SetupGenericShader(true);
4794 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))
4796 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4797 if (r_timereport_active)
4798 R_TimeReport("worlddebug");
4799 R_DrawModelsDebug();
4800 if (r_timereport_active)
4801 R_TimeReport("modeldebug");
4804 R_SetupGenericShader(true);
4806 if (cl.csqc_vidvars.drawworld)
4809 if (r_timereport_active)
4810 R_TimeReport("coronas");
4813 // don't let sound skip if going slow
4814 if (r_refdef.scene.extraupdate)
4817 R_ResetViewRendering2D();
4820 static const unsigned short bboxelements[36] =
4830 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4833 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4834 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4835 GL_DepthMask(false);
4836 GL_DepthRange(0, 1);
4837 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4838 R_Mesh_Matrix(&identitymatrix);
4839 R_Mesh_ResetTextureState();
4841 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4842 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4843 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4844 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4845 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4846 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4847 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4848 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4849 R_FillColors(color4f, 8, cr, cg, cb, ca);
4850 if (r_refdef.fogenabled)
4852 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4854 f1 = FogPoint_World(v);
4856 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4857 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4858 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4861 R_Mesh_VertexPointer(vertex3f, 0, 0);
4862 R_Mesh_ColorPointer(color4f, 0, 0);
4863 R_Mesh_ResetTextureState();
4864 R_SetupGenericShader(false);
4865 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4868 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4872 prvm_edict_t *edict;
4873 prvm_prog_t *prog_save = prog;
4875 // this function draws bounding boxes of server entities
4879 GL_CullFace(GL_NONE);
4880 R_SetupGenericShader(false);
4884 for (i = 0;i < numsurfaces;i++)
4886 edict = PRVM_EDICT_NUM(surfacelist[i]);
4887 switch ((int)edict->fields.server->solid)
4889 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4890 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4891 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4892 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4893 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4894 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4896 color[3] *= r_showbboxes.value;
4897 color[3] = bound(0, color[3], 1);
4898 GL_DepthTest(!r_showdisabledepthtest.integer);
4899 GL_CullFace(r_refdef.view.cullface_front);
4900 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4906 static void R_DrawEntityBBoxes(void)
4909 prvm_edict_t *edict;
4911 prvm_prog_t *prog_save = prog;
4913 // this function draws bounding boxes of server entities
4919 for (i = 0;i < prog->num_edicts;i++)
4921 edict = PRVM_EDICT_NUM(i);
4922 if (edict->priv.server->free)
4924 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4925 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4927 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4929 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4930 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4936 unsigned short nomodelelements[24] =
4948 float nomodelvertex3f[6*3] =
4958 float nomodelcolor4f[6*4] =
4960 0.0f, 0.0f, 0.5f, 1.0f,
4961 0.0f, 0.0f, 0.5f, 1.0f,
4962 0.0f, 0.5f, 0.0f, 1.0f,
4963 0.0f, 0.5f, 0.0f, 1.0f,
4964 0.5f, 0.0f, 0.0f, 1.0f,
4965 0.5f, 0.0f, 0.0f, 1.0f
4968 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4973 // this is only called once per entity so numsurfaces is always 1, and
4974 // surfacelist is always {0}, so this code does not handle batches
4975 R_Mesh_Matrix(&ent->matrix);
4977 if (ent->flags & EF_ADDITIVE)
4979 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4980 GL_DepthMask(false);
4982 else if (ent->alpha < 1)
4984 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4985 GL_DepthMask(false);
4989 GL_BlendFunc(GL_ONE, GL_ZERO);
4992 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4993 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4994 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4995 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4996 R_SetupGenericShader(false);
4997 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4998 if (r_refdef.fogenabled)
5001 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5002 R_Mesh_ColorPointer(color4f, 0, 0);
5003 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5004 f1 = FogPoint_World(org);
5006 for (i = 0, c = color4f;i < 6;i++, c += 4)
5008 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5009 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5010 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5014 else if (ent->alpha != 1)
5016 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5017 R_Mesh_ColorPointer(color4f, 0, 0);
5018 for (i = 0, c = color4f;i < 6;i++, c += 4)
5022 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
5023 R_Mesh_ResetTextureState();
5024 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
5027 void R_DrawNoModel(entity_render_t *ent)
5030 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5031 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
5032 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5034 // R_DrawNoModelCallback(ent, 0);
5037 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5039 vec3_t right1, right2, diff, normal;
5041 VectorSubtract (org2, org1, normal);
5043 // calculate 'right' vector for start
5044 VectorSubtract (r_refdef.view.origin, org1, diff);
5045 CrossProduct (normal, diff, right1);
5046 VectorNormalize (right1);
5048 // calculate 'right' vector for end
5049 VectorSubtract (r_refdef.view.origin, org2, diff);
5050 CrossProduct (normal, diff, right2);
5051 VectorNormalize (right2);
5053 vert[ 0] = org1[0] + width * right1[0];
5054 vert[ 1] = org1[1] + width * right1[1];
5055 vert[ 2] = org1[2] + width * right1[2];
5056 vert[ 3] = org1[0] - width * right1[0];
5057 vert[ 4] = org1[1] - width * right1[1];
5058 vert[ 5] = org1[2] - width * right1[2];
5059 vert[ 6] = org2[0] - width * right2[0];
5060 vert[ 7] = org2[1] - width * right2[1];
5061 vert[ 8] = org2[2] - width * right2[2];
5062 vert[ 9] = org2[0] + width * right2[0];
5063 vert[10] = org2[1] + width * right2[1];
5064 vert[11] = org2[2] + width * right2[2];
5067 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
5069 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)
5071 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
5075 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
5076 fog = FogPoint_World(origin);
5078 R_Mesh_Matrix(&identitymatrix);
5079 GL_BlendFunc(blendfunc1, blendfunc2);
5081 GL_CullFace(GL_NONE);
5083 GL_DepthMask(false);
5084 GL_DepthRange(0, depthshort ? 0.0625 : 1);
5085 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5086 GL_DepthTest(!depthdisable);
5088 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5089 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5090 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5091 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5092 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5093 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5094 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5095 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5096 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5097 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5098 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5099 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5101 R_Mesh_VertexPointer(vertex3f, 0, 0);
5102 R_Mesh_ColorPointer(NULL, 0, 0);
5103 R_Mesh_ResetTextureState();
5104 R_SetupGenericShader(true);
5105 R_Mesh_TexBind(0, R_GetTexture(texture));
5106 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5107 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5108 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5109 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5111 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5113 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5114 GL_BlendFunc(blendfunc1, GL_ONE);
5116 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5117 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5121 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5126 VectorSet(v, x, y, z);
5127 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5128 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5130 if (i == mesh->numvertices)
5132 if (mesh->numvertices < mesh->maxvertices)
5134 VectorCopy(v, vertex3f);
5135 mesh->numvertices++;
5137 return mesh->numvertices;
5143 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5147 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5148 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5149 e = mesh->element3i + mesh->numtriangles * 3;
5150 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5152 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5153 if (mesh->numtriangles < mesh->maxtriangles)
5158 mesh->numtriangles++;
5160 element[1] = element[2];
5164 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5168 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5169 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5170 e = mesh->element3i + mesh->numtriangles * 3;
5171 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5173 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5174 if (mesh->numtriangles < mesh->maxtriangles)
5179 mesh->numtriangles++;
5181 element[1] = element[2];
5185 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5186 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5188 int planenum, planenum2;
5191 mplane_t *plane, *plane2;
5193 double temppoints[2][256*3];
5194 // figure out how large a bounding box we need to properly compute this brush
5196 for (w = 0;w < numplanes;w++)
5197 maxdist = max(maxdist, planes[w].dist);
5198 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5199 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5200 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5204 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5205 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5207 if (planenum2 == planenum)
5209 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);
5212 if (tempnumpoints < 3)
5214 // generate elements forming a triangle fan for this polygon
5215 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5219 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)
5221 texturelayer_t *layer;
5222 layer = t->currentlayers + t->currentnumlayers++;
5224 layer->depthmask = depthmask;
5225 layer->blendfunc1 = blendfunc1;
5226 layer->blendfunc2 = blendfunc2;
5227 layer->texture = texture;
5228 layer->texmatrix = *matrix;
5229 layer->color[0] = r * r_refdef.view.colorscale;
5230 layer->color[1] = g * r_refdef.view.colorscale;
5231 layer->color[2] = b * r_refdef.view.colorscale;
5232 layer->color[3] = a;
5235 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5238 index = parms[2] + r_refdef.scene.time * parms[3];
5239 index -= floor(index);
5243 case Q3WAVEFUNC_NONE:
5244 case Q3WAVEFUNC_NOISE:
5245 case Q3WAVEFUNC_COUNT:
5248 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5249 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5250 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5251 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5252 case Q3WAVEFUNC_TRIANGLE:
5254 f = index - floor(index);
5265 return (float)(parms[0] + parms[1] * f);
5268 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5273 matrix4x4_t matrix, temp;
5274 switch(tcmod->tcmod)
5278 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5279 matrix = r_waterscrollmatrix;
5281 matrix = identitymatrix;
5283 case Q3TCMOD_ENTITYTRANSLATE:
5284 // this is used in Q3 to allow the gamecode to control texcoord
5285 // scrolling on the entity, which is not supported in darkplaces yet.
5286 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5288 case Q3TCMOD_ROTATE:
5289 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5290 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5291 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5294 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5296 case Q3TCMOD_SCROLL:
5297 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5299 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5300 w = (int) tcmod->parms[0];
5301 h = (int) tcmod->parms[1];
5302 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5304 idx = (int) floor(f * w * h);
5305 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5307 case Q3TCMOD_STRETCH:
5308 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5309 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5311 case Q3TCMOD_TRANSFORM:
5312 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5313 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5314 VectorSet(tcmat + 6, 0 , 0 , 1);
5315 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5316 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5318 case Q3TCMOD_TURBULENT:
5319 // this is handled in the RSurf_PrepareVertices function
5320 matrix = identitymatrix;
5324 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5327 texture_t *R_GetCurrentTexture(texture_t *t)
5330 const entity_render_t *ent = rsurface.entity;
5331 dp_model_t *model = ent->model;
5332 q3shaderinfo_layer_tcmod_t *tcmod;
5334 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5335 return t->currentframe;
5336 t->update_lastrenderframe = r_frame;
5337 t->update_lastrenderentity = (void *)ent;
5339 // switch to an alternate material if this is a q1bsp animated material
5341 texture_t *texture = t;
5342 int s = ent->skinnum;
5343 if ((unsigned int)s >= (unsigned int)model->numskins)
5345 if (model->skinscenes)
5347 if (model->skinscenes[s].framecount > 1)
5348 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5350 s = model->skinscenes[s].firstframe;
5353 t = t + s * model->num_surfaces;
5356 // use an alternate animation if the entity's frame is not 0,
5357 // and only if the texture has an alternate animation
5358 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
5359 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5361 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5363 texture->currentframe = t;
5366 // update currentskinframe to be a qw skin or animation frame
5367 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"))
5369 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
5371 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
5372 if (developer_loading.integer)
5373 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
5374 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);
5376 t->currentskinframe = r_qwskincache_skinframe[i];
5377 if (t->currentskinframe == NULL)
5378 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5380 else if (t->numskinframes >= 2)
5381 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5382 if (t->backgroundnumskinframes >= 2)
5383 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
5385 t->currentmaterialflags = t->basematerialflags;
5386 t->currentalpha = ent->alpha;
5387 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5388 t->currentalpha *= r_wateralpha.value;
5389 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5390 t->currentalpha *= t->r_water_wateralpha;
5391 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5392 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5393 if (!(ent->flags & RENDER_LIGHT))
5394 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5395 else if (rsurface.modeltexcoordlightmap2f == NULL)
5397 // pick a model lighting mode
5398 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5399 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5401 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5403 if (ent->effects & EF_ADDITIVE)
5404 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5405 else if (t->currentalpha < 1)
5406 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5407 if (ent->effects & EF_DOUBLESIDED)
5408 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5409 if (ent->effects & EF_NODEPTHTEST)
5410 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5411 if (ent->flags & RENDER_VIEWMODEL)
5412 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5413 if (t->backgroundnumskinframes)
5414 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5415 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5417 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5418 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5421 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5423 // there is no tcmod
5424 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5426 t->currenttexmatrix = r_waterscrollmatrix;
5427 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5431 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5432 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5435 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5436 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5437 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5438 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5440 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5441 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5442 t->glosstexture = r_texture_black;
5443 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5444 t->backgroundglosstexture = r_texture_black;
5445 t->specularpower = r_shadow_glossexponent.value;
5446 // TODO: store reference values for these in the texture?
5447 t->specularscale = 0;
5448 if (r_shadow_gloss.integer > 0)
5450 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5452 if (r_shadow_glossintensity.value > 0)
5454 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5455 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5456 t->specularscale = r_shadow_glossintensity.value;
5459 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5461 t->glosstexture = r_texture_white;
5462 t->backgroundglosstexture = r_texture_white;
5463 t->specularscale = r_shadow_gloss2intensity.value;
5467 // lightmaps mode looks bad with dlights using actual texturing, so turn
5468 // off the colormap and glossmap, but leave the normalmap on as it still
5469 // accurately represents the shading involved
5470 if (gl_lightmaps.integer)
5472 t->basetexture = r_texture_grey128;
5473 t->backgroundbasetexture = NULL;
5474 t->specularscale = 0;
5475 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5478 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5479 VectorClear(t->dlightcolor);
5480 t->currentnumlayers = 0;
5481 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5484 int blendfunc1, blendfunc2;
5486 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5488 blendfunc1 = GL_SRC_ALPHA;
5489 blendfunc2 = GL_ONE;
5491 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5493 blendfunc1 = GL_SRC_ALPHA;
5494 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5496 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5498 blendfunc1 = t->customblendfunc[0];
5499 blendfunc2 = t->customblendfunc[1];
5503 blendfunc1 = GL_ONE;
5504 blendfunc2 = GL_ZERO;
5506 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5507 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5508 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5509 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5511 // fullbright is not affected by r_refdef.lightmapintensity
5512 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]);
5513 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5514 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]);
5515 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5516 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]);
5520 vec3_t ambientcolor;
5522 // set the color tint used for lights affecting this surface
5523 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5525 // q3bsp has no lightmap updates, so the lightstylevalue that
5526 // would normally be baked into the lightmap must be
5527 // applied to the color
5528 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5529 if (ent->model->type == mod_brushq3)
5530 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5531 colorscale *= r_refdef.lightmapintensity;
5532 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5533 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5534 // basic lit geometry
5535 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]);
5536 // add pants/shirt if needed
5537 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5538 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]);
5539 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5540 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]);
5541 // now add ambient passes if needed
5542 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5544 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]);
5545 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5546 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]);
5547 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5548 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]);
5551 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5552 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]);
5553 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5555 // if this is opaque use alpha blend which will darken the earlier
5558 // if this is an alpha blended material, all the earlier passes
5559 // were darkened by fog already, so we only need to add the fog
5560 // color ontop through the fog mask texture
5562 // if this is an additive blended material, all the earlier passes
5563 // were darkened by fog already, and we should not add fog color
5564 // (because the background was not darkened, there is no fog color
5565 // that was lost behind it).
5566 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]);
5570 return t->currentframe;
5573 rsurfacestate_t rsurface;
5575 void R_Mesh_ResizeArrays(int newvertices)
5578 if (rsurface.array_size >= newvertices)
5580 if (rsurface.array_modelvertex3f)
5581 Mem_Free(rsurface.array_modelvertex3f);
5582 rsurface.array_size = (newvertices + 1023) & ~1023;
5583 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5584 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5585 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5586 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5587 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5588 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5589 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5590 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5591 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5592 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5593 rsurface.array_color4f = base + rsurface.array_size * 27;
5594 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5597 void RSurf_ActiveWorldEntity(void)
5599 dp_model_t *model = r_refdef.scene.worldmodel;
5600 //if (rsurface.entity == r_refdef.scene.worldentity)
5602 rsurface.entity = r_refdef.scene.worldentity;
5603 if (rsurface.array_size < model->surfmesh.num_vertices)
5604 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5605 rsurface.matrix = identitymatrix;
5606 rsurface.inversematrix = identitymatrix;
5607 R_Mesh_Matrix(&identitymatrix);
5608 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5609 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5610 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5611 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5612 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5613 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5614 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5615 rsurface.frameblend[0].lerp = 1;
5616 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5617 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5618 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5619 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5620 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5621 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5622 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5623 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5624 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5625 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5626 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5627 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5628 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5629 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5630 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5631 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5632 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5633 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5634 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5635 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5636 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5637 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5638 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5639 rsurface.modelelement3i = model->surfmesh.data_element3i;
5640 rsurface.modelelement3s = model->surfmesh.data_element3s;
5641 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5642 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5643 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5644 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5645 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5646 rsurface.modelsurfaces = model->data_surfaces;
5647 rsurface.generatedvertex = false;
5648 rsurface.vertex3f = rsurface.modelvertex3f;
5649 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5650 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5651 rsurface.svector3f = rsurface.modelsvector3f;
5652 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5653 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5654 rsurface.tvector3f = rsurface.modeltvector3f;
5655 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5656 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5657 rsurface.normal3f = rsurface.modelnormal3f;
5658 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5659 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5660 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5663 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5665 dp_model_t *model = ent->model;
5666 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5668 rsurface.entity = (entity_render_t *)ent;
5669 if (rsurface.array_size < model->surfmesh.num_vertices)
5670 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5671 rsurface.matrix = ent->matrix;
5672 rsurface.inversematrix = ent->inversematrix;
5673 R_Mesh_Matrix(&rsurface.matrix);
5674 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5675 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5676 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5677 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5678 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5679 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5680 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5681 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5682 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5683 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5684 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5685 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5686 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5687 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5688 if (ent->model->brush.submodel)
5690 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5691 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5693 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5695 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5697 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5698 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5699 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5700 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5702 else if (wanttangents)
5704 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5705 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5706 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5707 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5708 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5710 else if (wantnormals)
5712 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5713 rsurface.modelsvector3f = NULL;
5714 rsurface.modeltvector3f = NULL;
5715 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5716 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5720 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5721 rsurface.modelsvector3f = NULL;
5722 rsurface.modeltvector3f = NULL;
5723 rsurface.modelnormal3f = NULL;
5724 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5726 rsurface.modelvertex3f_bufferobject = 0;
5727 rsurface.modelvertex3f_bufferoffset = 0;
5728 rsurface.modelsvector3f_bufferobject = 0;
5729 rsurface.modelsvector3f_bufferoffset = 0;
5730 rsurface.modeltvector3f_bufferobject = 0;
5731 rsurface.modeltvector3f_bufferoffset = 0;
5732 rsurface.modelnormal3f_bufferobject = 0;
5733 rsurface.modelnormal3f_bufferoffset = 0;
5734 rsurface.generatedvertex = true;
5738 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5739 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5740 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5741 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5742 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5743 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5744 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5745 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5746 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5747 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5748 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5749 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5750 rsurface.generatedvertex = false;
5752 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5753 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5754 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5755 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5756 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5757 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5758 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5759 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5760 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5761 rsurface.modelelement3i = model->surfmesh.data_element3i;
5762 rsurface.modelelement3s = model->surfmesh.data_element3s;
5763 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5764 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5765 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5766 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5767 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5768 rsurface.modelsurfaces = model->data_surfaces;
5769 rsurface.vertex3f = rsurface.modelvertex3f;
5770 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5771 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5772 rsurface.svector3f = rsurface.modelsvector3f;
5773 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5774 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5775 rsurface.tvector3f = rsurface.modeltvector3f;
5776 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5777 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5778 rsurface.normal3f = rsurface.modelnormal3f;
5779 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5780 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5781 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5784 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5785 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5788 int texturesurfaceindex;
5793 const float *v1, *in_tc;
5795 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5797 q3shaderinfo_deform_t *deform;
5798 // 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
5799 if (rsurface.generatedvertex)
5801 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5802 generatenormals = true;
5803 for (i = 0;i < Q3MAXDEFORMS;i++)
5805 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5807 generatetangents = true;
5808 generatenormals = true;
5810 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5811 generatenormals = true;
5813 if (generatenormals && !rsurface.modelnormal3f)
5815 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5816 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5817 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5818 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
5820 if (generatetangents && !rsurface.modelsvector3f)
5822 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5823 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5824 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5825 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5826 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5827 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5828 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);
5831 rsurface.vertex3f = rsurface.modelvertex3f;
5832 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5833 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5834 rsurface.svector3f = rsurface.modelsvector3f;
5835 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5836 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5837 rsurface.tvector3f = rsurface.modeltvector3f;
5838 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5839 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5840 rsurface.normal3f = rsurface.modelnormal3f;
5841 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5842 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5843 // if vertices are deformed (sprite flares and things in maps, possibly
5844 // water waves, bulges and other deformations), generate them into
5845 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5846 // (may be static model data or generated data for an animated model, or
5847 // the previous deform pass)
5848 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5850 switch (deform->deform)
5853 case Q3DEFORM_PROJECTIONSHADOW:
5854 case Q3DEFORM_TEXT0:
5855 case Q3DEFORM_TEXT1:
5856 case Q3DEFORM_TEXT2:
5857 case Q3DEFORM_TEXT3:
5858 case Q3DEFORM_TEXT4:
5859 case Q3DEFORM_TEXT5:
5860 case Q3DEFORM_TEXT6:
5861 case Q3DEFORM_TEXT7:
5864 case Q3DEFORM_AUTOSPRITE:
5865 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5866 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5867 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5868 VectorNormalize(newforward);
5869 VectorNormalize(newright);
5870 VectorNormalize(newup);
5871 // make deformed versions of only the model vertices used by the specified surfaces
5872 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5874 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5875 // a single autosprite surface can contain multiple sprites...
5876 for (j = 0;j < surface->num_vertices - 3;j += 4)
5878 VectorClear(center);
5879 for (i = 0;i < 4;i++)
5880 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5881 VectorScale(center, 0.25f, center);
5882 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5883 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5884 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5885 for (i = 0;i < 4;i++)
5887 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5888 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5891 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);
5892 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);
5894 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5895 rsurface.vertex3f_bufferobject = 0;
5896 rsurface.vertex3f_bufferoffset = 0;
5897 rsurface.svector3f = rsurface.array_deformedsvector3f;
5898 rsurface.svector3f_bufferobject = 0;
5899 rsurface.svector3f_bufferoffset = 0;
5900 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5901 rsurface.tvector3f_bufferobject = 0;
5902 rsurface.tvector3f_bufferoffset = 0;
5903 rsurface.normal3f = rsurface.array_deformednormal3f;
5904 rsurface.normal3f_bufferobject = 0;
5905 rsurface.normal3f_bufferoffset = 0;
5907 case Q3DEFORM_AUTOSPRITE2:
5908 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5909 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5910 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5911 VectorNormalize(newforward);
5912 VectorNormalize(newright);
5913 VectorNormalize(newup);
5914 // make deformed versions of only the model vertices used by the specified surfaces
5915 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5917 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5918 const float *v1, *v2;
5928 memset(shortest, 0, sizeof(shortest));
5929 // a single autosprite surface can contain multiple sprites...
5930 for (j = 0;j < surface->num_vertices - 3;j += 4)
5932 VectorClear(center);
5933 for (i = 0;i < 4;i++)
5934 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5935 VectorScale(center, 0.25f, center);
5936 // find the two shortest edges, then use them to define the
5937 // axis vectors for rotating around the central axis
5938 for (i = 0;i < 6;i++)
5940 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5941 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5943 Debug_PolygonBegin(NULL, 0);
5944 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5945 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);
5946 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5949 l = VectorDistance2(v1, v2);
5950 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5952 l += (1.0f / 1024.0f);
5953 if (shortest[0].length2 > l || i == 0)
5955 shortest[1] = shortest[0];
5956 shortest[0].length2 = l;
5957 shortest[0].v1 = v1;
5958 shortest[0].v2 = v2;
5960 else if (shortest[1].length2 > l || i == 1)
5962 shortest[1].length2 = l;
5963 shortest[1].v1 = v1;
5964 shortest[1].v2 = v2;
5967 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5968 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5970 Debug_PolygonBegin(NULL, 0);
5971 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5972 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);
5973 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5976 // this calculates the right vector from the shortest edge
5977 // and the up vector from the edge midpoints
5978 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5979 VectorNormalize(right);
5980 VectorSubtract(end, start, up);
5981 VectorNormalize(up);
5982 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5983 VectorSubtract(rsurface.modelorg, center, forward);
5984 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5985 VectorNegate(forward, forward);
5986 VectorReflect(forward, 0, up, forward);
5987 VectorNormalize(forward);
5988 CrossProduct(up, forward, newright);
5989 VectorNormalize(newright);
5991 Debug_PolygonBegin(NULL, 0);
5992 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);
5993 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5994 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5998 Debug_PolygonBegin(NULL, 0);
5999 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6000 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6001 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6004 // rotate the quad around the up axis vector, this is made
6005 // especially easy by the fact we know the quad is flat,
6006 // so we only have to subtract the center position and
6007 // measure distance along the right vector, and then
6008 // multiply that by the newright vector and add back the
6010 // we also need to subtract the old position to undo the
6011 // displacement from the center, which we do with a
6012 // DotProduct, the subtraction/addition of center is also
6013 // optimized into DotProducts here
6014 l = DotProduct(right, center);
6015 for (i = 0;i < 4;i++)
6017 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6018 f = DotProduct(right, v1) - l;
6019 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6022 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);
6023 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);
6025 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6026 rsurface.vertex3f_bufferobject = 0;
6027 rsurface.vertex3f_bufferoffset = 0;
6028 rsurface.svector3f = rsurface.array_deformedsvector3f;
6029 rsurface.svector3f_bufferobject = 0;
6030 rsurface.svector3f_bufferoffset = 0;
6031 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6032 rsurface.tvector3f_bufferobject = 0;
6033 rsurface.tvector3f_bufferoffset = 0;
6034 rsurface.normal3f = rsurface.array_deformednormal3f;
6035 rsurface.normal3f_bufferobject = 0;
6036 rsurface.normal3f_bufferoffset = 0;
6038 case Q3DEFORM_NORMAL:
6039 // deform the normals to make reflections wavey
6040 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6042 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6043 for (j = 0;j < surface->num_vertices;j++)
6046 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6047 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6048 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6049 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6050 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6051 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6052 VectorNormalize(normal);
6054 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);
6056 rsurface.svector3f = rsurface.array_deformedsvector3f;
6057 rsurface.svector3f_bufferobject = 0;
6058 rsurface.svector3f_bufferoffset = 0;
6059 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6060 rsurface.tvector3f_bufferobject = 0;
6061 rsurface.tvector3f_bufferoffset = 0;
6062 rsurface.normal3f = rsurface.array_deformednormal3f;
6063 rsurface.normal3f_bufferobject = 0;
6064 rsurface.normal3f_bufferoffset = 0;
6067 // deform vertex array to make wavey water and flags and such
6068 waveparms[0] = deform->waveparms[0];
6069 waveparms[1] = deform->waveparms[1];
6070 waveparms[2] = deform->waveparms[2];
6071 waveparms[3] = deform->waveparms[3];
6072 // this is how a divisor of vertex influence on deformation
6073 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6074 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6075 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6077 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6078 for (j = 0;j < surface->num_vertices;j++)
6080 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6081 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6082 // if the wavefunc depends on time, evaluate it per-vertex
6085 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6086 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6088 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6091 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6092 rsurface.vertex3f_bufferobject = 0;
6093 rsurface.vertex3f_bufferoffset = 0;
6095 case Q3DEFORM_BULGE:
6096 // deform vertex array to make the surface have moving bulges
6097 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6099 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6100 for (j = 0;j < surface->num_vertices;j++)
6102 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6103 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6106 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6107 rsurface.vertex3f_bufferobject = 0;
6108 rsurface.vertex3f_bufferoffset = 0;
6111 // deform vertex array
6112 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6113 VectorScale(deform->parms, scale, waveparms);
6114 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6116 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6117 for (j = 0;j < surface->num_vertices;j++)
6118 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6120 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6121 rsurface.vertex3f_bufferobject = 0;
6122 rsurface.vertex3f_bufferoffset = 0;
6126 // generate texcoords based on the chosen texcoord source
6127 switch(rsurface.texture->tcgen.tcgen)
6130 case Q3TCGEN_TEXTURE:
6131 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6132 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6133 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6135 case Q3TCGEN_LIGHTMAP:
6136 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6137 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6138 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6140 case Q3TCGEN_VECTOR:
6141 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6143 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6144 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)
6146 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6147 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6150 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6151 rsurface.texcoordtexture2f_bufferobject = 0;
6152 rsurface.texcoordtexture2f_bufferoffset = 0;
6154 case Q3TCGEN_ENVIRONMENT:
6155 // make environment reflections using a spheremap
6156 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6158 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6159 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6160 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6161 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6162 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6164 // identical to Q3A's method, but executed in worldspace so
6165 // carried models can be shiny too
6167 float viewer[3], d, reflected[3], worldreflected[3];
6169 VectorSubtract(rsurface.modelorg, vertex, viewer);
6170 // VectorNormalize(viewer);
6172 d = DotProduct(normal, viewer);
6174 reflected[0] = normal[0]*2*d - viewer[0];
6175 reflected[1] = normal[1]*2*d - viewer[1];
6176 reflected[2] = normal[2]*2*d - viewer[2];
6177 // note: this is proportinal to viewer, so we can normalize later
6179 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6180 VectorNormalize(worldreflected);
6182 // note: this sphere map only uses world x and z!
6183 // so positive and negative y will LOOK THE SAME.
6184 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6185 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6188 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6189 rsurface.texcoordtexture2f_bufferobject = 0;
6190 rsurface.texcoordtexture2f_bufferoffset = 0;
6193 // the only tcmod that needs software vertex processing is turbulent, so
6194 // check for it here and apply the changes if needed
6195 // and we only support that as the first one
6196 // (handling a mixture of turbulent and other tcmods would be problematic
6197 // without punting it entirely to a software path)
6198 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6200 amplitude = rsurface.texture->tcmods[0].parms[1];
6201 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6202 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6204 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6205 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)
6207 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6208 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6211 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6212 rsurface.texcoordtexture2f_bufferobject = 0;
6213 rsurface.texcoordtexture2f_bufferoffset = 0;
6215 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6216 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6217 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6218 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6221 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6224 const msurface_t *surface = texturesurfacelist[0];
6225 const msurface_t *surface2;
6230 // TODO: lock all array ranges before render, rather than on each surface
6231 if (texturenumsurfaces == 1)
6233 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6234 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);
6236 else if (r_batchmode.integer == 2)
6238 #define MAXBATCHTRIANGLES 4096
6239 int batchtriangles = 0;
6240 int batchelements[MAXBATCHTRIANGLES*3];
6241 for (i = 0;i < texturenumsurfaces;i = j)
6243 surface = texturesurfacelist[i];
6245 if (surface->num_triangles > MAXBATCHTRIANGLES)
6247 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);
6250 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6251 batchtriangles = surface->num_triangles;
6252 firstvertex = surface->num_firstvertex;
6253 endvertex = surface->num_firstvertex + surface->num_vertices;
6254 for (;j < texturenumsurfaces;j++)
6256 surface2 = texturesurfacelist[j];
6257 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6259 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6260 batchtriangles += surface2->num_triangles;
6261 firstvertex = min(firstvertex, surface2->num_firstvertex);
6262 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6264 surface2 = texturesurfacelist[j-1];
6265 numvertices = endvertex - firstvertex;
6266 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6269 else if (r_batchmode.integer == 1)
6271 for (i = 0;i < texturenumsurfaces;i = j)
6273 surface = texturesurfacelist[i];
6274 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6275 if (texturesurfacelist[j] != surface2)
6277 surface2 = texturesurfacelist[j-1];
6278 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6279 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6280 GL_LockArrays(surface->num_firstvertex, numvertices);
6281 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6286 for (i = 0;i < texturenumsurfaces;i++)
6288 surface = texturesurfacelist[i];
6289 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6290 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);
6295 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6297 int i, planeindex, vertexindex;
6301 r_waterstate_waterplane_t *p, *bestp;
6302 msurface_t *surface;
6303 if (r_waterstate.renderingscene)
6305 for (i = 0;i < texturenumsurfaces;i++)
6307 surface = texturesurfacelist[i];
6308 if (lightmaptexunit >= 0)
6309 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6310 if (deluxemaptexunit >= 0)
6311 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6312 // pick the closest matching water plane
6315 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6318 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6320 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6321 d += fabs(PlaneDiff(vert, &p->plane));
6323 if (bestd > d || !bestp)
6331 if (refractiontexunit >= 0)
6332 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6333 if (reflectiontexunit >= 0)
6334 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6338 if (refractiontexunit >= 0)
6339 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6340 if (reflectiontexunit >= 0)
6341 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6343 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6344 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);
6348 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6352 const msurface_t *surface = texturesurfacelist[0];
6353 const msurface_t *surface2;
6358 // TODO: lock all array ranges before render, rather than on each surface
6359 if (texturenumsurfaces == 1)
6361 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6362 if (deluxemaptexunit >= 0)
6363 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6364 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6365 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);
6367 else if (r_batchmode.integer == 2)
6369 #define MAXBATCHTRIANGLES 4096
6370 int batchtriangles = 0;
6371 int batchelements[MAXBATCHTRIANGLES*3];
6372 for (i = 0;i < texturenumsurfaces;i = j)
6374 surface = texturesurfacelist[i];
6375 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6376 if (deluxemaptexunit >= 0)
6377 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6379 if (surface->num_triangles > MAXBATCHTRIANGLES)
6381 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);
6384 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6385 batchtriangles = surface->num_triangles;
6386 firstvertex = surface->num_firstvertex;
6387 endvertex = surface->num_firstvertex + surface->num_vertices;
6388 for (;j < texturenumsurfaces;j++)
6390 surface2 = texturesurfacelist[j];
6391 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6393 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6394 batchtriangles += surface2->num_triangles;
6395 firstvertex = min(firstvertex, surface2->num_firstvertex);
6396 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6398 surface2 = texturesurfacelist[j-1];
6399 numvertices = endvertex - firstvertex;
6400 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6403 else if (r_batchmode.integer == 1)
6406 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6407 for (i = 0;i < texturenumsurfaces;i = j)
6409 surface = texturesurfacelist[i];
6410 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6411 if (texturesurfacelist[j] != surface2)
6413 Con_Printf(" %i", j - i);
6416 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6418 for (i = 0;i < texturenumsurfaces;i = j)
6420 surface = texturesurfacelist[i];
6421 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6422 if (deluxemaptexunit >= 0)
6423 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6424 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6425 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6428 Con_Printf(" %i", j - i);
6430 surface2 = texturesurfacelist[j-1];
6431 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6432 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6433 GL_LockArrays(surface->num_firstvertex, numvertices);
6434 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6442 for (i = 0;i < texturenumsurfaces;i++)
6444 surface = texturesurfacelist[i];
6445 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6446 if (deluxemaptexunit >= 0)
6447 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6448 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6449 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);
6454 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6457 int texturesurfaceindex;
6458 if (r_showsurfaces.integer == 2)
6460 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6462 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6463 for (j = 0;j < surface->num_triangles;j++)
6465 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6466 GL_Color(f, f, f, 1);
6467 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6473 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6475 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6476 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6477 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);
6478 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6479 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);
6484 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6486 int texturesurfaceindex;
6489 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6491 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6492 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)
6500 rsurface.lightmapcolor4f = rsurface.array_color4f;
6501 rsurface.lightmapcolor4f_bufferobject = 0;
6502 rsurface.lightmapcolor4f_bufferoffset = 0;
6505 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6507 int texturesurfaceindex;
6511 if (rsurface.lightmapcolor4f)
6513 // generate color arrays for the surfaces in this list
6514 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6516 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6517 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)
6519 f = FogPoint_Model(v);
6529 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6531 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6532 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)
6534 f = FogPoint_Model(v);
6542 rsurface.lightmapcolor4f = rsurface.array_color4f;
6543 rsurface.lightmapcolor4f_bufferobject = 0;
6544 rsurface.lightmapcolor4f_bufferoffset = 0;
6547 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6549 int texturesurfaceindex;
6553 if (!rsurface.lightmapcolor4f)
6555 // generate color arrays for the surfaces in this list
6556 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6558 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6559 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)
6561 f = FogPoint_Model(v);
6562 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6563 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6564 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6568 rsurface.lightmapcolor4f = rsurface.array_color4f;
6569 rsurface.lightmapcolor4f_bufferobject = 0;
6570 rsurface.lightmapcolor4f_bufferoffset = 0;
6573 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6575 int texturesurfaceindex;
6578 if (!rsurface.lightmapcolor4f)
6580 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6582 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6583 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)
6591 rsurface.lightmapcolor4f = rsurface.array_color4f;
6592 rsurface.lightmapcolor4f_bufferobject = 0;
6593 rsurface.lightmapcolor4f_bufferoffset = 0;
6596 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6598 int texturesurfaceindex;
6601 if (!rsurface.lightmapcolor4f)
6603 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6605 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6606 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)
6608 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6609 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6610 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6614 rsurface.lightmapcolor4f = rsurface.array_color4f;
6615 rsurface.lightmapcolor4f_bufferobject = 0;
6616 rsurface.lightmapcolor4f_bufferoffset = 0;
6619 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6622 rsurface.lightmapcolor4f = NULL;
6623 rsurface.lightmapcolor4f_bufferobject = 0;
6624 rsurface.lightmapcolor4f_bufferoffset = 0;
6625 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6626 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6627 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6628 GL_Color(r, g, b, a);
6629 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6632 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6634 // TODO: optimize applyfog && applycolor case
6635 // just apply fog if necessary, and tint the fog color array if necessary
6636 rsurface.lightmapcolor4f = NULL;
6637 rsurface.lightmapcolor4f_bufferobject = 0;
6638 rsurface.lightmapcolor4f_bufferoffset = 0;
6639 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6640 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6641 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6642 GL_Color(r, g, b, a);
6643 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6646 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6648 int texturesurfaceindex;
6652 if (texturesurfacelist[0]->lightmapinfo)
6654 // generate color arrays for the surfaces in this list
6655 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6657 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6658 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6660 if (surface->lightmapinfo->samples)
6662 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6663 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6664 VectorScale(lm, scale, c);
6665 if (surface->lightmapinfo->styles[1] != 255)
6667 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6669 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6670 VectorMA(c, scale, lm, c);
6671 if (surface->lightmapinfo->styles[2] != 255)
6674 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6675 VectorMA(c, scale, lm, c);
6676 if (surface->lightmapinfo->styles[3] != 255)
6679 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6680 VectorMA(c, scale, lm, c);
6690 rsurface.lightmapcolor4f = rsurface.array_color4f;
6691 rsurface.lightmapcolor4f_bufferobject = 0;
6692 rsurface.lightmapcolor4f_bufferoffset = 0;
6696 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6697 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6698 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6700 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6701 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6702 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6703 GL_Color(r, g, b, a);
6704 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6707 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6709 int texturesurfaceindex;
6712 float *v, *c, *c2, alpha;
6713 vec3_t ambientcolor;
6714 vec3_t diffusecolor;
6718 VectorCopy(rsurface.modellight_lightdir, lightdir);
6719 f = 0.5f * r_refdef.lightmapintensity;
6720 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6721 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6722 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6723 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6724 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6725 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6727 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6729 // generate color arrays for the surfaces in this list
6730 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6732 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6733 int numverts = surface->num_vertices;
6734 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6735 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6736 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6737 // q3-style directional shading
6738 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6740 if ((f = DotProduct(c2, lightdir)) > 0)
6741 VectorMA(ambientcolor, f, diffusecolor, c);
6743 VectorCopy(ambientcolor, c);
6751 rsurface.lightmapcolor4f = rsurface.array_color4f;
6752 rsurface.lightmapcolor4f_bufferobject = 0;
6753 rsurface.lightmapcolor4f_bufferoffset = 0;
6754 *applycolor = false;
6758 *r = ambientcolor[0];
6759 *g = ambientcolor[1];
6760 *b = ambientcolor[2];
6761 rsurface.lightmapcolor4f = NULL;
6762 rsurface.lightmapcolor4f_bufferobject = 0;
6763 rsurface.lightmapcolor4f_bufferoffset = 0;
6767 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6769 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6770 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6771 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6772 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6773 GL_Color(r, g, b, a);
6774 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6777 void RSurf_SetupDepthAndCulling(void)
6779 // submodels are biased to avoid z-fighting with world surfaces that they
6780 // may be exactly overlapping (avoids z-fighting artifacts on certain
6781 // doors and things in Quake maps)
6782 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6783 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6784 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6785 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6788 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6790 // transparent sky would be ridiculous
6791 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6793 R_SetupGenericShader(false);
6796 skyrendernow = false;
6797 // we have to force off the water clipping plane while rendering sky
6801 // restore entity matrix
6802 R_Mesh_Matrix(&rsurface.matrix);
6804 RSurf_SetupDepthAndCulling();
6806 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6807 // skymasking on them, and Quake3 never did sky masking (unlike
6808 // software Quake and software Quake2), so disable the sky masking
6809 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6810 // and skymasking also looks very bad when noclipping outside the
6811 // level, so don't use it then either.
6812 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6814 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6815 R_Mesh_ColorPointer(NULL, 0, 0);
6816 R_Mesh_ResetTextureState();
6817 if (skyrendermasked)
6819 R_SetupDepthOrShadowShader();
6820 // depth-only (masking)
6821 GL_ColorMask(0,0,0,0);
6822 // just to make sure that braindead drivers don't draw
6823 // anything despite that colormask...
6824 GL_BlendFunc(GL_ZERO, GL_ONE);
6828 R_SetupGenericShader(false);
6830 GL_BlendFunc(GL_ONE, GL_ZERO);
6832 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6833 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6834 if (skyrendermasked)
6835 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6837 R_Mesh_ResetTextureState();
6838 GL_Color(1, 1, 1, 1);
6841 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6843 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6846 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6847 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6848 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6849 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6850 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6851 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6852 if (rsurface.texture->backgroundcurrentskinframe)
6854 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6855 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6856 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6857 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6859 if(rsurface.texture->colormapping)
6861 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6862 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6864 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6865 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6866 R_Mesh_ColorPointer(NULL, 0, 0);
6868 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6870 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6872 // render background
6873 GL_BlendFunc(GL_ONE, GL_ZERO);
6875 GL_AlphaTest(false);
6877 GL_Color(1, 1, 1, 1);
6878 R_Mesh_ColorPointer(NULL, 0, 0);
6880 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6881 if (r_glsl_permutation)
6883 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6884 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6885 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6886 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6887 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6888 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6889 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);
6891 GL_LockArrays(0, 0);
6893 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6894 GL_DepthMask(false);
6895 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6896 R_Mesh_ColorPointer(NULL, 0, 0);
6898 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6899 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6900 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6903 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6904 if (!r_glsl_permutation)
6907 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6908 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6909 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6910 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6911 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6912 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6914 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6916 GL_BlendFunc(GL_ONE, GL_ZERO);
6918 GL_AlphaTest(false);
6922 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6923 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6924 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6927 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6929 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6930 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);
6932 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6936 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6937 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);
6939 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6941 GL_LockArrays(0, 0);
6944 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6946 // OpenGL 1.3 path - anything not completely ancient
6947 int texturesurfaceindex;
6948 qboolean applycolor;
6952 const texturelayer_t *layer;
6953 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6955 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6958 int layertexrgbscale;
6959 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6961 if (layerindex == 0)
6965 GL_AlphaTest(false);
6966 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6969 GL_DepthMask(layer->depthmask && writedepth);
6970 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6971 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6973 layertexrgbscale = 4;
6974 VectorScale(layer->color, 0.25f, layercolor);
6976 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6978 layertexrgbscale = 2;
6979 VectorScale(layer->color, 0.5f, layercolor);
6983 layertexrgbscale = 1;
6984 VectorScale(layer->color, 1.0f, layercolor);
6986 layercolor[3] = layer->color[3];
6987 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6988 R_Mesh_ColorPointer(NULL, 0, 0);
6989 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6990 switch (layer->type)
6992 case TEXTURELAYERTYPE_LITTEXTURE:
6993 memset(&m, 0, sizeof(m));
6994 m.tex[0] = R_GetTexture(r_texture_white);
6995 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6996 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6997 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6998 m.tex[1] = R_GetTexture(layer->texture);
6999 m.texmatrix[1] = layer->texmatrix;
7000 m.texrgbscale[1] = layertexrgbscale;
7001 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7002 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7003 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7004 R_Mesh_TextureState(&m);
7005 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7006 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7007 else if (rsurface.uselightmaptexture)
7008 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7010 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7012 case TEXTURELAYERTYPE_TEXTURE:
7013 memset(&m, 0, sizeof(m));
7014 m.tex[0] = R_GetTexture(layer->texture);
7015 m.texmatrix[0] = layer->texmatrix;
7016 m.texrgbscale[0] = layertexrgbscale;
7017 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7018 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7019 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7020 R_Mesh_TextureState(&m);
7021 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7023 case TEXTURELAYERTYPE_FOG:
7024 memset(&m, 0, sizeof(m));
7025 m.texrgbscale[0] = layertexrgbscale;
7028 m.tex[0] = R_GetTexture(layer->texture);
7029 m.texmatrix[0] = layer->texmatrix;
7030 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7031 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7032 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7034 R_Mesh_TextureState(&m);
7035 // generate a color array for the fog pass
7036 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7037 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7041 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7042 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)
7044 f = 1 - FogPoint_Model(v);
7045 c[0] = layercolor[0];
7046 c[1] = layercolor[1];
7047 c[2] = layercolor[2];
7048 c[3] = f * layercolor[3];
7051 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7054 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7056 GL_LockArrays(0, 0);
7059 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7061 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7062 GL_AlphaTest(false);
7066 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7068 // OpenGL 1.1 - crusty old voodoo path
7069 int texturesurfaceindex;
7073 const texturelayer_t *layer;
7074 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7076 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7078 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7080 if (layerindex == 0)
7084 GL_AlphaTest(false);
7085 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7088 GL_DepthMask(layer->depthmask && writedepth);
7089 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7090 R_Mesh_ColorPointer(NULL, 0, 0);
7091 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7092 switch (layer->type)
7094 case TEXTURELAYERTYPE_LITTEXTURE:
7095 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7097 // two-pass lit texture with 2x rgbscale
7098 // first the lightmap pass
7099 memset(&m, 0, sizeof(m));
7100 m.tex[0] = R_GetTexture(r_texture_white);
7101 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7102 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7103 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7104 R_Mesh_TextureState(&m);
7105 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7106 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7107 else if (rsurface.uselightmaptexture)
7108 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7110 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7111 GL_LockArrays(0, 0);
7112 // then apply the texture to it
7113 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7114 memset(&m, 0, sizeof(m));
7115 m.tex[0] = R_GetTexture(layer->texture);
7116 m.texmatrix[0] = layer->texmatrix;
7117 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7118 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7119 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7120 R_Mesh_TextureState(&m);
7121 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);
7125 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7126 memset(&m, 0, sizeof(m));
7127 m.tex[0] = R_GetTexture(layer->texture);
7128 m.texmatrix[0] = layer->texmatrix;
7129 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7130 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7131 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7132 R_Mesh_TextureState(&m);
7133 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7134 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);
7136 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);
7139 case TEXTURELAYERTYPE_TEXTURE:
7140 // singletexture unlit texture with transparency support
7141 memset(&m, 0, sizeof(m));
7142 m.tex[0] = R_GetTexture(layer->texture);
7143 m.texmatrix[0] = layer->texmatrix;
7144 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7145 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7146 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7147 R_Mesh_TextureState(&m);
7148 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);
7150 case TEXTURELAYERTYPE_FOG:
7151 // singletexture fogging
7152 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7155 memset(&m, 0, sizeof(m));
7156 m.tex[0] = R_GetTexture(layer->texture);
7157 m.texmatrix[0] = layer->texmatrix;
7158 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7159 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7160 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7161 R_Mesh_TextureState(&m);
7164 R_Mesh_ResetTextureState();
7165 // generate a color array for the fog pass
7166 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7170 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7171 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)
7173 f = 1 - FogPoint_Model(v);
7174 c[0] = layer->color[0];
7175 c[1] = layer->color[1];
7176 c[2] = layer->color[2];
7177 c[3] = f * layer->color[3];
7180 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7183 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7185 GL_LockArrays(0, 0);
7188 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7190 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7191 GL_AlphaTest(false);
7195 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7199 GL_AlphaTest(false);
7200 R_Mesh_ColorPointer(NULL, 0, 0);
7201 R_Mesh_ResetTextureState();
7202 R_SetupGenericShader(false);
7204 if(rsurface.texture && rsurface.texture->currentskinframe)
7206 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7207 c[3] *= rsurface.texture->currentalpha;
7217 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7219 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7220 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7221 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7224 // brighten it up (as texture value 127 means "unlit")
7225 c[0] *= 2 * r_refdef.view.colorscale;
7226 c[1] *= 2 * r_refdef.view.colorscale;
7227 c[2] *= 2 * r_refdef.view.colorscale;
7229 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7230 c[3] *= r_wateralpha.value;
7232 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7234 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7235 GL_DepthMask(false);
7237 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7239 GL_BlendFunc(GL_ONE, GL_ONE);
7240 GL_DepthMask(false);
7242 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7244 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7245 GL_DepthMask(false);
7247 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7249 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7250 GL_DepthMask(false);
7254 GL_BlendFunc(GL_ONE, GL_ZERO);
7255 GL_DepthMask(writedepth);
7258 rsurface.lightmapcolor4f = NULL;
7260 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7262 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7264 rsurface.lightmapcolor4f = NULL;
7265 rsurface.lightmapcolor4f_bufferobject = 0;
7266 rsurface.lightmapcolor4f_bufferoffset = 0;
7268 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7270 qboolean applycolor = true;
7273 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7275 r_refdef.lightmapintensity = 1;
7276 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7277 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7281 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7283 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7284 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7285 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7288 if(!rsurface.lightmapcolor4f)
7289 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7291 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7292 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7293 if(r_refdef.fogenabled)
7294 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7296 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7297 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7300 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7303 RSurf_SetupDepthAndCulling();
7304 if (r_showsurfaces.integer == 3)
7305 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7306 else if (r_glsl.integer && gl_support_fragment_shader)
7307 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7308 else if (gl_combine.integer && r_textureunits.integer >= 2)
7309 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7311 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7315 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7318 RSurf_SetupDepthAndCulling();
7319 if (r_showsurfaces.integer == 3)
7320 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7321 else if (r_glsl.integer && gl_support_fragment_shader)
7322 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7323 else if (gl_combine.integer && r_textureunits.integer >= 2)
7324 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7326 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7330 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7333 int texturenumsurfaces, endsurface;
7335 msurface_t *surface;
7336 msurface_t *texturesurfacelist[1024];
7338 // if the model is static it doesn't matter what value we give for
7339 // wantnormals and wanttangents, so this logic uses only rules applicable
7340 // to a model, knowing that they are meaningless otherwise
7341 if (ent == r_refdef.scene.worldentity)
7342 RSurf_ActiveWorldEntity();
7343 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7344 RSurf_ActiveModelEntity(ent, false, false);
7346 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7348 for (i = 0;i < numsurfaces;i = j)
7351 surface = rsurface.modelsurfaces + surfacelist[i];
7352 texture = surface->texture;
7353 rsurface.texture = R_GetCurrentTexture(texture);
7354 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7355 // scan ahead until we find a different texture
7356 endsurface = min(i + 1024, numsurfaces);
7357 texturenumsurfaces = 0;
7358 texturesurfacelist[texturenumsurfaces++] = surface;
7359 for (;j < endsurface;j++)
7361 surface = rsurface.modelsurfaces + surfacelist[j];
7362 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7364 texturesurfacelist[texturenumsurfaces++] = surface;
7366 // render the range of surfaces
7367 if (ent == r_refdef.scene.worldentity)
7368 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7370 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7372 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7373 GL_AlphaTest(false);
7376 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7378 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7382 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7384 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7386 RSurf_SetupDepthAndCulling();
7387 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7388 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7390 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7392 RSurf_SetupDepthAndCulling();
7393 GL_AlphaTest(false);
7394 R_Mesh_ColorPointer(NULL, 0, 0);
7395 R_Mesh_ResetTextureState();
7396 R_SetupGenericShader(false);
7397 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7399 GL_BlendFunc(GL_ONE, GL_ZERO);
7400 GL_Color(0, 0, 0, 1);
7401 GL_DepthTest(writedepth);
7402 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7404 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7406 RSurf_SetupDepthAndCulling();
7407 GL_AlphaTest(false);
7408 R_Mesh_ColorPointer(NULL, 0, 0);
7409 R_Mesh_ResetTextureState();
7410 R_SetupGenericShader(false);
7411 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7413 GL_BlendFunc(GL_ONE, GL_ZERO);
7415 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7417 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7418 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7419 else if (!rsurface.texture->currentnumlayers)
7421 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7423 // transparent surfaces get pushed off into the transparent queue
7424 int surfacelistindex;
7425 const msurface_t *surface;
7426 vec3_t tempcenter, center;
7427 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7429 surface = texturesurfacelist[surfacelistindex];
7430 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7431 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7432 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7433 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7434 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7439 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7440 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7445 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7449 // break the surface list down into batches by texture and use of lightmapping
7450 for (i = 0;i < numsurfaces;i = j)
7453 // texture is the base texture pointer, rsurface.texture is the
7454 // current frame/skin the texture is directing us to use (for example
7455 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7456 // use skin 1 instead)
7457 texture = surfacelist[i]->texture;
7458 rsurface.texture = R_GetCurrentTexture(texture);
7459 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7460 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7462 // if this texture is not the kind we want, skip ahead to the next one
7463 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7467 // simply scan ahead until we find a different texture or lightmap state
7468 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7470 // render the range of surfaces
7471 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7475 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7480 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7482 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7484 RSurf_SetupDepthAndCulling();
7485 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7486 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7488 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7490 RSurf_SetupDepthAndCulling();
7491 GL_AlphaTest(false);
7492 R_Mesh_ColorPointer(NULL, 0, 0);
7493 R_Mesh_ResetTextureState();
7494 R_SetupGenericShader(false);
7495 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7497 GL_BlendFunc(GL_ONE, GL_ZERO);
7498 GL_Color(0, 0, 0, 1);
7499 GL_DepthTest(writedepth);
7500 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7502 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7504 RSurf_SetupDepthAndCulling();
7505 GL_AlphaTest(false);
7506 R_Mesh_ColorPointer(NULL, 0, 0);
7507 R_Mesh_ResetTextureState();
7508 R_SetupGenericShader(false);
7509 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7511 GL_BlendFunc(GL_ONE, GL_ZERO);
7513 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7515 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7516 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7517 else if (!rsurface.texture->currentnumlayers)
7519 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7521 // transparent surfaces get pushed off into the transparent queue
7522 int surfacelistindex;
7523 const msurface_t *surface;
7524 vec3_t tempcenter, center;
7525 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7527 surface = texturesurfacelist[surfacelistindex];
7528 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7529 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7530 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7531 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7532 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7537 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7538 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7543 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7547 // break the surface list down into batches by texture and use of lightmapping
7548 for (i = 0;i < numsurfaces;i = j)
7551 // texture is the base texture pointer, rsurface.texture is the
7552 // current frame/skin the texture is directing us to use (for example
7553 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7554 // use skin 1 instead)
7555 texture = surfacelist[i]->texture;
7556 rsurface.texture = R_GetCurrentTexture(texture);
7557 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7558 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7560 // if this texture is not the kind we want, skip ahead to the next one
7561 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7565 // simply scan ahead until we find a different texture or lightmap state
7566 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7568 // render the range of surfaces
7569 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7573 float locboxvertex3f[6*4*3] =
7575 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7576 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7577 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7578 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7579 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7580 1,0,0, 0,0,0, 0,1,0, 1,1,0
7583 unsigned short locboxelements[6*2*3] =
7593 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7596 cl_locnode_t *loc = (cl_locnode_t *)ent;
7598 float vertex3f[6*4*3];
7600 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7601 GL_DepthMask(false);
7602 GL_DepthRange(0, 1);
7603 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7605 GL_CullFace(GL_NONE);
7606 R_Mesh_Matrix(&identitymatrix);
7608 R_Mesh_VertexPointer(vertex3f, 0, 0);
7609 R_Mesh_ColorPointer(NULL, 0, 0);
7610 R_Mesh_ResetTextureState();
7611 R_SetupGenericShader(false);
7614 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7615 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7616 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7617 surfacelist[0] < 0 ? 0.5f : 0.125f);
7619 if (VectorCompare(loc->mins, loc->maxs))
7621 VectorSet(size, 2, 2, 2);
7622 VectorMA(loc->mins, -0.5f, size, mins);
7626 VectorCopy(loc->mins, mins);
7627 VectorSubtract(loc->maxs, loc->mins, size);
7630 for (i = 0;i < 6*4*3;)
7631 for (j = 0;j < 3;j++, i++)
7632 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7634 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7637 void R_DrawLocs(void)
7640 cl_locnode_t *loc, *nearestloc;
7642 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7643 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7645 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7646 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7650 void R_DrawDebugModel(entity_render_t *ent)
7652 int i, j, k, l, flagsmask;
7653 const int *elements;
7655 msurface_t *surface;
7656 dp_model_t *model = ent->model;
7659 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7661 R_Mesh_ColorPointer(NULL, 0, 0);
7662 R_Mesh_ResetTextureState();
7663 R_SetupGenericShader(false);
7664 GL_DepthRange(0, 1);
7665 GL_DepthTest(!r_showdisabledepthtest.integer);
7666 GL_DepthMask(false);
7667 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7669 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7671 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7672 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7674 if (brush->colbrushf && brush->colbrushf->numtriangles)
7676 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7677 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);
7678 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7681 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7683 if (surface->num_collisiontriangles)
7685 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7686 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);
7687 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7692 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7694 if (r_showtris.integer || r_shownormals.integer)
7696 if (r_showdisabledepthtest.integer)
7698 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7699 GL_DepthMask(false);
7703 GL_BlendFunc(GL_ONE, GL_ZERO);
7706 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7708 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7710 rsurface.texture = R_GetCurrentTexture(surface->texture);
7711 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7713 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7714 if (r_showtris.value > 0)
7716 if (!rsurface.texture->currentlayers->depthmask)
7717 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7718 else if (ent == r_refdef.scene.worldentity)
7719 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7721 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7722 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7723 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7724 R_Mesh_ColorPointer(NULL, 0, 0);
7725 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7726 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7727 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7728 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);
7729 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7732 if (r_shownormals.value < 0)
7735 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7737 VectorCopy(rsurface.vertex3f + l * 3, v);
7738 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7739 qglVertex3f(v[0], v[1], v[2]);
7740 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7741 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7742 qglVertex3f(v[0], v[1], v[2]);
7747 if (r_shownormals.value > 0)
7750 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7752 VectorCopy(rsurface.vertex3f + l * 3, v);
7753 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7754 qglVertex3f(v[0], v[1], v[2]);
7755 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7756 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7757 qglVertex3f(v[0], v[1], v[2]);
7762 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7764 VectorCopy(rsurface.vertex3f + l * 3, v);
7765 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7766 qglVertex3f(v[0], v[1], v[2]);
7767 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7768 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7769 qglVertex3f(v[0], v[1], v[2]);
7774 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7776 VectorCopy(rsurface.vertex3f + l * 3, v);
7777 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7778 qglVertex3f(v[0], v[1], v[2]);
7779 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7780 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7781 qglVertex3f(v[0], v[1], v[2]);
7788 rsurface.texture = NULL;
7792 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7793 int r_maxsurfacelist = 0;
7794 msurface_t **r_surfacelist = NULL;
7795 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7797 int i, j, endj, f, flagsmask;
7799 dp_model_t *model = r_refdef.scene.worldmodel;
7800 msurface_t *surfaces;
7801 unsigned char *update;
7802 int numsurfacelist = 0;
7806 if (r_maxsurfacelist < model->num_surfaces)
7808 r_maxsurfacelist = model->num_surfaces;
7810 Mem_Free(r_surfacelist);
7811 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7814 RSurf_ActiveWorldEntity();
7816 surfaces = model->data_surfaces;
7817 update = model->brushq1.lightmapupdateflags;
7819 // update light styles on this submodel
7820 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7822 model_brush_lightstyleinfo_t *style;
7823 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7825 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7827 int *list = style->surfacelist;
7828 style->value = r_refdef.scene.lightstylevalue[style->style];
7829 for (j = 0;j < style->numsurfaces;j++)
7830 update[list[j]] = true;
7835 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7839 R_DrawDebugModel(r_refdef.scene.worldentity);
7840 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7846 rsurface.uselightmaptexture = false;
7847 rsurface.texture = NULL;
7848 rsurface.rtlight = NULL;
7850 // add visible surfaces to draw list
7851 for (i = 0;i < model->nummodelsurfaces;i++)
7853 j = model->sortedmodelsurfaces[i];
7854 if (r_refdef.viewcache.world_surfacevisible[j])
7855 r_surfacelist[numsurfacelist++] = surfaces + j;
7857 // update lightmaps if needed
7859 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7860 if (r_refdef.viewcache.world_surfacevisible[j])
7862 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7863 // don't do anything if there were no surfaces
7864 if (!numsurfacelist)
7866 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7869 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7870 GL_AlphaTest(false);
7872 // add to stats if desired
7873 if (r_speeds.integer && !skysurfaces && !depthonly)
7875 r_refdef.stats.world_surfaces += numsurfacelist;
7876 for (j = 0;j < numsurfacelist;j++)
7877 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7879 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7882 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7884 int i, j, endj, f, flagsmask;
7886 dp_model_t *model = ent->model;
7887 msurface_t *surfaces;
7888 unsigned char *update;
7889 int numsurfacelist = 0;
7893 if (r_maxsurfacelist < model->num_surfaces)
7895 r_maxsurfacelist = model->num_surfaces;
7897 Mem_Free(r_surfacelist);
7898 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7901 // if the model is static it doesn't matter what value we give for
7902 // wantnormals and wanttangents, so this logic uses only rules applicable
7903 // to a model, knowing that they are meaningless otherwise
7904 if (ent == r_refdef.scene.worldentity)
7905 RSurf_ActiveWorldEntity();
7906 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7907 RSurf_ActiveModelEntity(ent, false, false);
7909 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7911 surfaces = model->data_surfaces;
7912 update = model->brushq1.lightmapupdateflags;
7914 // update light styles
7915 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7917 model_brush_lightstyleinfo_t *style;
7918 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7920 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7922 int *list = style->surfacelist;
7923 style->value = r_refdef.scene.lightstylevalue[style->style];
7924 for (j = 0;j < style->numsurfaces;j++)
7925 update[list[j]] = true;
7930 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7934 R_DrawDebugModel(ent);
7935 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7941 rsurface.uselightmaptexture = false;
7942 rsurface.texture = NULL;
7943 rsurface.rtlight = NULL;
7945 // add visible surfaces to draw list
7946 for (i = 0;i < model->nummodelsurfaces;i++)
7947 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7948 // don't do anything if there were no surfaces
7949 if (!numsurfacelist)
7951 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7954 // update lightmaps if needed
7956 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7958 R_BuildLightMap(ent, surfaces + j);
7959 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7960 GL_AlphaTest(false);
7962 // add to stats if desired
7963 if (r_speeds.integer && !skysurfaces && !depthonly)
7965 r_refdef.stats.entities_surfaces += numsurfacelist;
7966 for (j = 0;j < numsurfacelist;j++)
7967 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7969 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity