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 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
48 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
49 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
50 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
51 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
53 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
55 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"};
56 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
57 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
58 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
59 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
60 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
61 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)"};
62 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
63 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
64 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"};
65 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"};
66 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
67 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"};
68 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"};
69 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"};
70 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
71 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
72 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
73 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
74 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
75 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
76 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
77 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
78 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
79 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
80 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
81 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
82 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."};
83 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
84 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
85 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
86 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."};
87 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
88 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
89 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"};
90 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
91 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
92 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
93 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
94 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
96 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
97 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
98 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
99 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
100 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
101 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
102 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
103 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
105 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)"};
107 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
108 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)"};
109 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
110 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
111 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
112 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
113 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)"};
114 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)"};
115 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)"};
116 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)"};
117 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)"};
119 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)"};
120 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
121 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"};
122 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
123 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
125 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
126 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
127 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
128 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
130 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
131 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
132 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
133 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
134 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
135 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
136 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
138 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
139 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
140 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
141 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)"};
143 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"};
145 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"};
147 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
149 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
150 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
151 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"};
152 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
153 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
154 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
155 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
157 extern cvar_t v_glslgamma;
159 extern qboolean v_flipped_state;
161 static struct r_bloomstate_s
166 int bloomwidth, bloomheight;
168 int screentexturewidth, screentextureheight;
169 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
171 int bloomtexturewidth, bloomtextureheight;
172 rtexture_t *texture_bloom;
174 // arrays for rendering the screen passes
175 float screentexcoord2f[8];
176 float bloomtexcoord2f[8];
177 float offsettexcoord2f[8];
179 r_viewport_t viewport;
183 r_waterstate_t r_waterstate;
185 /// shadow volume bsp struct with automatically growing nodes buffer
188 rtexture_t *r_texture_blanknormalmap;
189 rtexture_t *r_texture_white;
190 rtexture_t *r_texture_grey128;
191 rtexture_t *r_texture_black;
192 rtexture_t *r_texture_notexture;
193 rtexture_t *r_texture_whitecube;
194 rtexture_t *r_texture_normalizationcube;
195 rtexture_t *r_texture_fogattenuation;
196 rtexture_t *r_texture_gammaramps;
197 unsigned int r_texture_gammaramps_serial;
198 //rtexture_t *r_texture_fogintensity;
200 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
201 unsigned int r_numqueries;
202 unsigned int r_maxqueries;
204 typedef struct r_qwskincache_s
206 char name[MAX_QPATH];
207 skinframe_t *skinframe;
211 static r_qwskincache_t *r_qwskincache;
212 static int r_qwskincache_size;
214 /// vertex coordinates for a quad that covers the screen exactly
215 const float r_screenvertex3f[12] =
223 extern void R_DrawModelShadows(void);
225 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
228 for (i = 0;i < verts;i++)
239 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
242 for (i = 0;i < verts;i++)
252 // FIXME: move this to client?
255 if (gamemode == GAME_NEHAHRA)
257 Cvar_Set("gl_fogenable", "0");
258 Cvar_Set("gl_fogdensity", "0.2");
259 Cvar_Set("gl_fogred", "0.3");
260 Cvar_Set("gl_foggreen", "0.3");
261 Cvar_Set("gl_fogblue", "0.3");
263 r_refdef.fog_density = 0;
264 r_refdef.fog_red = 0;
265 r_refdef.fog_green = 0;
266 r_refdef.fog_blue = 0;
267 r_refdef.fog_alpha = 1;
268 r_refdef.fog_start = 0;
269 r_refdef.fog_end = 16384;
270 r_refdef.fog_height = 1<<30;
271 r_refdef.fog_fadedepth = 128;
274 static void R_BuildBlankTextures(void)
276 unsigned char data[4];
277 data[2] = 128; // normal X
278 data[1] = 128; // normal Y
279 data[0] = 255; // normal Z
280 data[3] = 128; // height
281 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
286 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
291 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
296 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
299 static void R_BuildNoTexture(void)
302 unsigned char pix[16][16][4];
303 // this makes a light grey/dark grey checkerboard texture
304 for (y = 0;y < 16;y++)
306 for (x = 0;x < 16;x++)
308 if ((y < 8) ^ (x < 8))
324 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
327 static void R_BuildWhiteCube(void)
329 unsigned char data[6*1*1*4];
330 memset(data, 255, sizeof(data));
331 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
334 static void R_BuildNormalizationCube(void)
338 vec_t s, t, intensity;
340 unsigned char data[6][NORMSIZE][NORMSIZE][4];
341 for (side = 0;side < 6;side++)
343 for (y = 0;y < NORMSIZE;y++)
345 for (x = 0;x < NORMSIZE;x++)
347 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
348 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
383 intensity = 127.0f / sqrt(DotProduct(v, v));
384 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
385 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
386 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
387 data[side][y][x][3] = 255;
391 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
394 static void R_BuildFogTexture(void)
398 unsigned char data1[FOGWIDTH][4];
399 //unsigned char data2[FOGWIDTH][4];
402 r_refdef.fogmasktable_start = r_refdef.fog_start;
403 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
404 r_refdef.fogmasktable_range = r_refdef.fogrange;
405 r_refdef.fogmasktable_density = r_refdef.fog_density;
407 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
408 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
410 d = (x * r - r_refdef.fogmasktable_start);
411 if(developer.integer >= 100)
412 Con_Printf("%f ", d);
414 if (r_fog_exp2.integer)
415 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
417 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
418 if(developer.integer >= 100)
419 Con_Printf(" : %f ", alpha);
420 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
421 if(developer.integer >= 100)
422 Con_Printf(" = %f\n", alpha);
423 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
426 for (x = 0;x < FOGWIDTH;x++)
428 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
433 //data2[x][0] = 255 - b;
434 //data2[x][1] = 255 - b;
435 //data2[x][2] = 255 - b;
438 if (r_texture_fogattenuation)
440 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
441 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
445 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);
446 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
450 static const char *builtinshaderstring =
451 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
452 "// written by Forest 'LordHavoc' Hale\n"
454 "// enable various extensions depending on permutation:\n"
456 "#ifdef USESHADOWMAPRECT\n"
457 "# extension GL_ARB_texture_rectangle : enable\n"
460 "#ifdef USESHADOWMAP2D\n"
461 "# ifdef GL_EXT_gpu_shader4\n"
462 "# extension GL_EXT_gpu_shader4 : enable\n"
464 "# ifdef GL_ARB_texture_gather\n"
465 "# extension GL_ARB_texture_gather : enable\n"
467 "# ifdef GL_AMD_texture_texture4\n"
468 "# extension GL_AMD_texture_texture4 : enable\n"
473 "#ifdef USESHADOWMAPCUBE\n"
474 "# extension GL_EXT_gpu_shader4 : enable\n"
477 "#ifdef USESHADOWSAMPLER\n"
478 "# extension GL_ARB_shadow : enable\n"
481 "// common definitions between vertex shader and fragment shader:\n"
483 "//#ifdef __GLSL_CG_DATA_TYPES\n"
484 "//# define myhalf half\n"
485 "//# define myhalf2 half2\n"
486 "//# define myhalf3half3\n"
487 "//# define myhalf4 half4\n"
489 "# define myhalf float\n"
490 "# define myhalf2 vec2\n"
491 "# define myhalf3 vec3\n"
492 "# define myhalf4 vec4\n"
495 "#ifdef USEFOGINSIDE\n"
498 "# ifdef USEFOGOUTSIDE\n"
503 "#ifdef MODE_DEPTH_OR_SHADOW\n"
505 "# ifdef VERTEX_SHADER\n"
508 " gl_Position = ftransform();\n"
513 "#ifdef MODE_SHOWDEPTH\n"
514 "# ifdef VERTEX_SHADER\n"
517 " gl_Position = ftransform();\n"
518 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
521 "# ifdef FRAGMENT_SHADER\n"
524 " gl_FragColor = gl_Color;\n"
528 "#else // !MODE_SHOWDEPTH\n"
530 "#ifdef MODE_POSTPROCESS\n"
531 "# ifdef VERTEX_SHADER\n"
534 " gl_FrontColor = gl_Color;\n"
535 " gl_Position = ftransform();\n"
536 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
538 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
542 "# ifdef FRAGMENT_SHADER\n"
544 "uniform sampler2D Texture_First;\n"
546 "uniform sampler2D Texture_Second;\n"
548 "#ifdef USEGAMMARAMPS\n"
549 "uniform sampler2D Texture_GammaRamps;\n"
551 "#ifdef USESATURATION\n"
552 "uniform float Saturation;\n"
554 "#ifdef USEVIEWTINT\n"
555 "uniform vec4 TintColor;\n"
557 "//uncomment these if you want to use them:\n"
558 "uniform vec4 UserVec1;\n"
559 "// uniform vec4 UserVec2;\n"
560 "// uniform vec4 UserVec3;\n"
561 "// uniform vec4 UserVec4;\n"
562 "// uniform float ClientTime;\n"
563 "uniform vec2 PixelSize;\n"
566 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
568 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
570 "#ifdef USEVIEWTINT\n"
571 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
574 "#ifdef USEPOSTPROCESSING\n"
575 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
576 "// 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"
577 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
578 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
579 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
580 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
581 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
582 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
585 "#ifdef USESATURATION\n"
586 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
587 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
588 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
589 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
592 "#ifdef USEGAMMARAMPS\n"
593 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
594 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
595 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
602 "#ifdef MODE_GENERIC\n"
603 "# ifdef VERTEX_SHADER\n"
606 " gl_FrontColor = gl_Color;\n"
607 "# ifdef USEDIFFUSE\n"
608 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
610 "# ifdef USESPECULAR\n"
611 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
613 " gl_Position = ftransform();\n"
616 "# ifdef FRAGMENT_SHADER\n"
618 "# ifdef USEDIFFUSE\n"
619 "uniform sampler2D Texture_First;\n"
621 "# ifdef USESPECULAR\n"
622 "uniform sampler2D Texture_Second;\n"
627 " gl_FragColor = gl_Color;\n"
628 "# ifdef USEDIFFUSE\n"
629 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
632 "# ifdef USESPECULAR\n"
633 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
635 "# ifdef USECOLORMAPPING\n"
636 " gl_FragColor *= tex2;\n"
639 " gl_FragColor += tex2;\n"
641 "# ifdef USEVERTEXTEXTUREBLEND\n"
642 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
647 "#else // !MODE_GENERIC\n"
648 "#ifdef MODE_BLOOMBLUR\n"
649 "# ifdef VERTEX_SHADER\n"
652 " gl_FrontColor = gl_Color;\n"
653 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
654 " gl_Position = ftransform();\n"
657 "# ifdef FRAGMENT_SHADER\n"
659 "uniform sampler2D Texture_First;\n"
660 "uniform vec4 BloomBlur_Parameters;\n"
665 " vec2 tc = gl_TexCoord[0].xy;\n"
666 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
667 " tc += BloomBlur_Parameters.xy;\n"
668 " for (i = 1;i < SAMPLES;i++)\n"
670 " color += texture2D(Texture_First, tc).rgb;\n"
671 " tc += BloomBlur_Parameters.xy;\n"
673 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
677 "#else // !MODE_BLOOMBLUR\n"
679 "varying vec2 TexCoord;\n"
680 "#ifdef USEVERTEXTEXTUREBLEND\n"
681 "varying vec2 TexCoord2;\n"
683 "varying vec2 TexCoordLightmap;\n"
685 "#ifdef MODE_LIGHTSOURCE\n"
686 "varying vec3 CubeVector;\n"
689 "#ifdef MODE_LIGHTSOURCE\n"
690 "varying vec3 LightVector;\n"
692 "#ifdef MODE_LIGHTDIRECTION\n"
693 "varying vec3 LightVector;\n"
696 "varying vec3 EyeVector;\n"
698 "varying vec3 EyeVectorModelSpace;\n"
699 "varying float FogPlaneVertexDist;\n"
702 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
703 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
704 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
706 "#ifdef MODE_WATER\n"
707 "varying vec4 ModelViewProjectionPosition;\n"
709 "#ifdef MODE_REFRACTION\n"
710 "varying vec4 ModelViewProjectionPosition;\n"
712 "#ifdef USEREFLECTION\n"
713 "varying vec4 ModelViewProjectionPosition;\n"
720 "// vertex shader specific:\n"
721 "#ifdef VERTEX_SHADER\n"
723 "uniform vec3 LightPosition;\n"
724 "uniform vec3 EyePosition;\n"
725 "uniform vec3 LightDir;\n"
726 "uniform vec4 FogPlane;\n"
728 "// 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"
732 " gl_FrontColor = gl_Color;\n"
733 " // copy the surface texcoord\n"
734 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
735 "#ifdef USEVERTEXTEXTUREBLEND\n"
736 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
738 "#ifndef MODE_LIGHTSOURCE\n"
739 "# ifndef MODE_LIGHTDIRECTION\n"
740 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
744 "#ifdef MODE_LIGHTSOURCE\n"
745 " // transform vertex position into light attenuation/cubemap space\n"
746 " // (-1 to +1 across the light box)\n"
747 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
749 " // transform unnormalized light direction into tangent space\n"
750 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
751 " // normalize it per pixel)\n"
752 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
753 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
754 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
755 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
758 "#ifdef MODE_LIGHTDIRECTION\n"
759 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
760 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
761 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
764 " // transform unnormalized eye direction into tangent space\n"
766 " vec3 EyeVectorModelSpace;\n"
768 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
769 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
770 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
771 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
774 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
777 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
778 " VectorS = gl_MultiTexCoord1.xyz;\n"
779 " VectorT = gl_MultiTexCoord2.xyz;\n"
780 " VectorR = gl_MultiTexCoord3.xyz;\n"
783 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
784 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
785 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
786 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
789 "// transform vertex to camera space, using ftransform to match non-VS\n"
791 " gl_Position = ftransform();\n"
793 "#ifdef MODE_WATER\n"
794 " ModelViewProjectionPosition = gl_Position;\n"
796 "#ifdef MODE_REFRACTION\n"
797 " ModelViewProjectionPosition = gl_Position;\n"
799 "#ifdef USEREFLECTION\n"
800 " ModelViewProjectionPosition = gl_Position;\n"
804 "#endif // VERTEX_SHADER\n"
809 "// fragment shader specific:\n"
810 "#ifdef FRAGMENT_SHADER\n"
812 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
813 "uniform sampler2D Texture_Normal;\n"
814 "uniform sampler2D Texture_Color;\n"
815 "uniform sampler2D Texture_Gloss;\n"
816 "uniform sampler2D Texture_Glow;\n"
817 "uniform sampler2D Texture_SecondaryNormal;\n"
818 "uniform sampler2D Texture_SecondaryColor;\n"
819 "uniform sampler2D Texture_SecondaryGloss;\n"
820 "uniform sampler2D Texture_SecondaryGlow;\n"
821 "uniform sampler2D Texture_Pants;\n"
822 "uniform sampler2D Texture_Shirt;\n"
823 "uniform sampler2D Texture_FogMask;\n"
824 "uniform sampler2D Texture_Lightmap;\n"
825 "uniform sampler2D Texture_Deluxemap;\n"
826 "uniform sampler2D Texture_Refraction;\n"
827 "uniform sampler2D Texture_Reflection;\n"
828 "uniform sampler2D Texture_Attenuation;\n"
829 "uniform samplerCube Texture_Cube;\n"
831 "#define showshadowmap 0\n"
833 "#ifdef USESHADOWMAPRECT\n"
834 "# ifdef USESHADOWSAMPLER\n"
835 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
837 "uniform sampler2DRect Texture_ShadowMapRect;\n"
841 "#ifdef USESHADOWMAP2D\n"
842 "# ifdef USESHADOWSAMPLER\n"
843 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
845 "uniform sampler2D Texture_ShadowMap2D;\n"
849 "#ifdef USESHADOWMAPVSDCT\n"
850 "uniform samplerCube Texture_CubeProjection;\n"
853 "#ifdef USESHADOWMAPCUBE\n"
854 "# ifdef USESHADOWSAMPLER\n"
855 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
857 "uniform samplerCube Texture_ShadowMapCube;\n"
861 "uniform myhalf3 LightColor;\n"
862 "uniform myhalf3 AmbientColor;\n"
863 "uniform myhalf3 DiffuseColor;\n"
864 "uniform myhalf3 SpecularColor;\n"
865 "uniform myhalf3 Color_Pants;\n"
866 "uniform myhalf3 Color_Shirt;\n"
867 "uniform myhalf3 FogColor;\n"
869 "uniform myhalf4 TintColor;\n"
872 "//#ifdef MODE_WATER\n"
873 "uniform vec4 DistortScaleRefractReflect;\n"
874 "uniform vec4 ScreenScaleRefractReflect;\n"
875 "uniform vec4 ScreenCenterRefractReflect;\n"
876 "uniform myhalf4 RefractColor;\n"
877 "uniform myhalf4 ReflectColor;\n"
878 "uniform myhalf ReflectFactor;\n"
879 "uniform myhalf ReflectOffset;\n"
881 "//# ifdef MODE_REFRACTION\n"
882 "//uniform vec4 DistortScaleRefractReflect;\n"
883 "//uniform vec4 ScreenScaleRefractReflect;\n"
884 "//uniform vec4 ScreenCenterRefractReflect;\n"
885 "//uniform myhalf4 RefractColor;\n"
886 "//# ifdef USEREFLECTION\n"
887 "//uniform myhalf4 ReflectColor;\n"
890 "//# ifdef USEREFLECTION\n"
891 "//uniform vec4 DistortScaleRefractReflect;\n"
892 "//uniform vec4 ScreenScaleRefractReflect;\n"
893 "//uniform vec4 ScreenCenterRefractReflect;\n"
894 "//uniform myhalf4 ReflectColor;\n"
899 "uniform myhalf3 GlowColor;\n"
900 "uniform myhalf SceneBrightness;\n"
902 "uniform float OffsetMapping_Scale;\n"
903 "uniform float OffsetMapping_Bias;\n"
904 "uniform float FogRangeRecip;\n"
905 "uniform float FogPlaneViewDist;\n"
906 "uniform float FogHeightFade;\n"
908 "uniform myhalf AmbientScale;\n"
909 "uniform myhalf DiffuseScale;\n"
910 "uniform myhalf SpecularScale;\n"
911 "uniform myhalf SpecularPower;\n"
913 "#ifdef USEOFFSETMAPPING\n"
914 "vec2 OffsetMapping(vec2 TexCoord)\n"
916 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
917 " // 14 sample relief mapping: linear search and then binary search\n"
918 " // this basically steps forward a small amount repeatedly until it finds\n"
919 " // itself inside solid, then jitters forward and back using decreasing\n"
920 " // amounts to find the impact\n"
921 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
922 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
923 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
924 " vec3 RT = vec3(TexCoord, 1);\n"
925 " OffsetVector *= 0.1;\n"
926 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
927 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
928 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
929 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
930 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
931 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
932 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
933 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
934 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
935 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
936 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
937 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
938 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
939 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
942 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
943 " // this basically moves forward the full distance, and then backs up based\n"
944 " // on height of samples\n"
945 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
946 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
947 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
948 " TexCoord += OffsetVector;\n"
949 " OffsetVector *= 0.333;\n"
950 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
951 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
952 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
953 " return TexCoord;\n"
956 "#endif // USEOFFSETMAPPING\n"
958 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
959 "uniform vec2 ShadowMap_TextureScale;\n"
960 "uniform vec4 ShadowMap_Parameters;\n"
963 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
964 "vec3 GetShadowMapTC2D(vec3 dir)\n"
966 " vec3 adir = abs(dir);\n"
967 "# ifndef USESHADOWMAPVSDCT\n"
971 " if (adir.x > adir.y)\n"
973 " if (adir.x > adir.z) // X\n"
977 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
983 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
988 " if (adir.y > adir.z) // Y\n"
992 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
998 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1002 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1003 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1004 " stc.z += ShadowMap_Parameters.z;\n"
1005 "# if showshadowmap\n"
1006 " stc.xy *= ShadowMap_TextureScale;\n"
1010 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1011 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1012 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1013 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1014 " stc.z += ShadowMap_Parameters.z;\n"
1015 "# if showshadowmap\n"
1016 " stc.xy *= ShadowMap_TextureScale;\n"
1021 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1023 "#ifdef USESHADOWMAPCUBE\n"
1024 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1026 " vec3 adir = abs(dir);\n"
1027 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1031 "#if !showshadowmap\n"
1032 "# ifdef USESHADOWMAPRECT\n"
1033 "float ShadowMapCompare(vec3 dir)\n"
1035 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1037 "# ifdef USESHADOWSAMPLER\n"
1039 "# ifdef USESHADOWMAPPCF\n"
1040 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1041 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1043 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1048 "# ifdef USESHADOWMAPPCF\n"
1049 "# if USESHADOWMAPPCF > 1\n"
1050 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1051 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1052 " vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1053 " vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
1054 " vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
1055 " vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
1056 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1057 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1059 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1060 " vec2 offset = fract(shadowmaptc.xy);\n"
1061 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1062 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1063 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1064 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1065 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1068 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1076 "# ifdef USESHADOWMAP2D\n"
1077 "float ShadowMapCompare(vec3 dir)\n"
1079 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1082 "# ifdef USESHADOWSAMPLER\n"
1083 "# ifdef USESHADOWMAPPCF\n"
1084 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1085 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1086 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1088 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1091 "# ifdef USESHADOWMAPPCF\n"
1092 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1093 "# ifdef GL_ARB_texture_gather\n"
1094 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1096 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1098 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1099 " center *= ShadowMap_TextureScale;\n"
1100 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1101 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1102 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1103 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1104 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1105 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1106 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1108 "# ifdef GL_EXT_gpu_shader4\n"
1109 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1111 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1113 "# if USESHADOWMAPPCF > 1\n"
1114 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1115 " center *= ShadowMap_TextureScale;\n"
1116 " vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1117 " vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
1118 " vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
1119 " vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
1120 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1121 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1123 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1124 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1125 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1126 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1127 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1128 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1132 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1139 "# ifdef USESHADOWMAPCUBE\n"
1140 "float ShadowMapCompare(vec3 dir)\n"
1142 " // apply depth texture cubemap as light filter\n"
1143 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1145 "# ifdef USESHADOWSAMPLER\n"
1146 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1148 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1155 "#ifdef MODE_WATER\n"
1160 "#ifdef USEOFFSETMAPPING\n"
1161 " // apply offsetmapping\n"
1162 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1163 "#define TexCoord TexCoordOffset\n"
1166 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1167 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1168 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1169 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1170 " // FIXME temporary hack to detect the case that the reflection\n"
1171 " // gets blackened at edges due to leaving the area that contains actual\n"
1173 " // Remove this 'ack once we have a better way to stop this thing from\n"
1175 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1176 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1177 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1178 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1179 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1180 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1181 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1182 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1183 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1184 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1185 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1186 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1189 "#else // !MODE_WATER\n"
1190 "#ifdef MODE_REFRACTION\n"
1192 "// refraction pass\n"
1195 "#ifdef USEOFFSETMAPPING\n"
1196 " // apply offsetmapping\n"
1197 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1198 "#define TexCoord TexCoordOffset\n"
1201 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1202 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1203 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1204 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1205 " // FIXME temporary hack to detect the case that the reflection\n"
1206 " // gets blackened at edges due to leaving the area that contains actual\n"
1208 " // Remove this 'ack once we have a better way to stop this thing from\n"
1210 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1211 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1212 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1213 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1214 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1215 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1218 "#else // !MODE_REFRACTION\n"
1221 "#ifdef USEOFFSETMAPPING\n"
1222 " // apply offsetmapping\n"
1223 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1224 "#define TexCoord TexCoordOffset\n"
1227 " // combine the diffuse textures (base, pants, shirt)\n"
1228 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1229 "#ifdef USECOLORMAPPING\n"
1230 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1232 "#ifdef USEVERTEXTEXTUREBLEND\n"
1233 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1234 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1235 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1236 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1238 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1241 "#ifdef USEDIFFUSE\n"
1242 " // get the surface normal and the gloss color\n"
1243 "# ifdef USEVERTEXTEXTUREBLEND\n"
1244 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1245 "# ifdef USESPECULAR\n"
1246 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1249 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1250 "# ifdef USESPECULAR\n"
1251 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1258 "#ifdef MODE_LIGHTSOURCE\n"
1259 " // light source\n"
1261 " // calculate surface normal, light normal, and specular normal\n"
1262 " // compute color intensity for the two textures (colormap and glossmap)\n"
1263 " // scale by light color and attenuation as efficiently as possible\n"
1264 " // (do as much scalar math as possible rather than vector math)\n"
1265 "# ifdef USEDIFFUSE\n"
1266 " // get the light normal\n"
1267 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1269 "# ifdef USESPECULAR\n"
1270 "# ifndef USEEXACTSPECULARMATH\n"
1271 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1274 " // calculate directional shading\n"
1275 "# ifdef USEEXACTSPECULARMATH\n"
1276 " 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"
1278 " 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"
1281 "# ifdef USEDIFFUSE\n"
1282 " // calculate directional shading\n"
1283 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1285 " // calculate directionless shading\n"
1286 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1290 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1291 "#if !showshadowmap\n"
1292 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1296 "# ifdef USECUBEFILTER\n"
1297 " // apply light cubemap filter\n"
1298 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1299 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1301 "#endif // MODE_LIGHTSOURCE\n"
1306 "#ifdef MODE_LIGHTDIRECTION\n"
1307 " // directional model lighting\n"
1308 "# ifdef USEDIFFUSE\n"
1309 " // get the light normal\n"
1310 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1312 "# ifdef USESPECULAR\n"
1313 " // calculate directional shading\n"
1314 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1315 "# ifdef USEEXACTSPECULARMATH\n"
1316 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1318 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1319 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1322 "# ifdef USEDIFFUSE\n"
1324 " // calculate directional shading\n"
1325 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1327 " color.rgb *= AmbientColor;\n"
1330 "#endif // MODE_LIGHTDIRECTION\n"
1335 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1336 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1338 " // get the light normal\n"
1339 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1340 " myhalf3 diffusenormal;\n"
1341 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1342 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1343 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1344 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1345 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1346 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1347 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1348 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1349 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1350 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1351 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1352 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1353 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1354 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1355 "# ifdef USESPECULAR\n"
1356 "# ifdef USEEXACTSPECULARMATH\n"
1357 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1359 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1360 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1364 " // apply lightmap color\n"
1365 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1366 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1371 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1372 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1374 " // get the light normal\n"
1375 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1376 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1377 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1378 "# ifdef USESPECULAR\n"
1379 "# ifdef USEEXACTSPECULARMATH\n"
1380 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1382 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1383 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1387 " // apply lightmap color\n"
1388 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1389 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1394 "#ifdef MODE_LIGHTMAP\n"
1395 " // apply lightmap color\n"
1396 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1397 "#endif // MODE_LIGHTMAP\n"
1402 "#ifdef MODE_VERTEXCOLOR\n"
1403 " // apply lightmap color\n"
1404 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1405 "#endif // MODE_VERTEXCOLOR\n"
1410 "#ifdef MODE_FLATCOLOR\n"
1411 "#endif // MODE_FLATCOLOR\n"
1419 " color *= TintColor;\n"
1422 "#ifdef USEVERTEXTEXTUREBLEND\n"
1423 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1425 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1429 " color.rgb *= SceneBrightness;\n"
1431 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1434 "#ifdef USEFOGOUTSIDE\n"
1435 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1437 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1439 "// float FogHeightFade1 = -0.5/1024.0;\n"
1440 "// if (FogPlaneViewDist >= 0.0)\n"
1441 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade1);\n"
1443 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade1);\n"
1444 "//# ifdef USEFOGABOVE\n"
1445 "// if (FogPlaneViewDist >= 0.0)\n"
1446 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist);\n"
1448 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist));\n"
1449 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1450 "// fogfrac *= min(1.0, (max(0.0, fade*FogPlaneVertexDist) + max(0.0, fade*FogPlaneViewDist)));\n"
1451 "// fogfrac *= min(1.0, (max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1452 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1454 " //fogfrac *= min(1.0, max(0.0, (max(-2048, min(0, FogPlaneVertexDist)) + max(-2048, min(0, FogPlaneViewDist)))/-2048.0));\n"
1455 " //float fade = -0.5/128.0;\n"
1456 " //fogfrac *= max(0.0, min(1.0, fade*FogPlaneVertexDist)) + max(0.0, min(1.0, fade*FogPlaneViewDist));\n"
1457 " //fogfrac *= max(0.0, min(1.0, FogHeightFade1*FogPlaneVertexDist)) + max(0.0, min(1.0, FogHeightFade1*FogPlaneViewDist));\n"
1458 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1459 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1460 " //fogfrac *= min(1.0, min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1461 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1462 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1463 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1465 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0))));\n"
1468 " // 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"
1469 "#ifdef USEREFLECTION\n"
1470 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1471 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1472 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1473 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1474 " // FIXME temporary hack to detect the case that the reflection\n"
1475 " // gets blackened at edges due to leaving the area that contains actual\n"
1477 " // Remove this 'ack once we have a better way to stop this thing from\n"
1479 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1480 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1481 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1482 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1483 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1484 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1487 " gl_FragColor = vec4(color);\n"
1489 "#if showshadowmap\n"
1490 "# ifdef USESHADOWMAPRECT\n"
1491 "# ifdef USESHADOWSAMPLER\n"
1492 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1494 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1497 "# ifdef USESHADOWMAP2D\n"
1498 "# ifdef USESHADOWSAMPLER\n"
1499 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1501 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1505 "# ifdef USESHADOWMAPCUBE\n"
1506 "# ifdef USESHADOWSAMPLER\n"
1507 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1509 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1514 "#endif // !MODE_REFRACTION\n"
1515 "#endif // !MODE_WATER\n"
1517 "#endif // FRAGMENT_SHADER\n"
1519 "#endif // !MODE_BLOOMBLUR\n"
1520 "#endif // !MODE_GENERIC\n"
1521 "#endif // !MODE_POSTPROCESS\n"
1522 "#endif // !MODE_SHOWDEPTH\n"
1523 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1526 typedef struct shaderpermutationinfo_s
1528 const char *pretext;
1531 shaderpermutationinfo_t;
1533 typedef struct shadermodeinfo_s
1535 const char *vertexfilename;
1536 const char *geometryfilename;
1537 const char *fragmentfilename;
1538 const char *pretext;
1543 typedef enum shaderpermutation_e
1545 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1546 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1547 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1548 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1549 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1550 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1551 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1552 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1553 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1554 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1555 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1556 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1557 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1558 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1559 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1560 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1561 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1562 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1563 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1564 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1565 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1566 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1567 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1568 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1569 SHADERPERMUTATION_LIMIT = 1<<24, ///< size of permutations array
1570 SHADERPERMUTATION_COUNT = 24 ///< size of shaderpermutationinfo array
1572 shaderpermutation_t;
1574 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1575 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1577 {"#define USEDIFFUSE\n", " diffuse"},
1578 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1579 {"#define USEVIEWTINT\n", " viewtint"},
1580 {"#define USECOLORMAPPING\n", " colormapping"},
1581 {"#define USESATURATION\n", " saturation"},
1582 {"#define USEFOGINSIDE\n", " foginside"},
1583 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1584 {"#define USEGAMMARAMPS\n", " gammaramps"},
1585 {"#define USECUBEFILTER\n", " cubefilter"},
1586 {"#define USEGLOW\n", " glow"},
1587 {"#define USEBLOOM\n", " bloom"},
1588 {"#define USESPECULAR\n", " specular"},
1589 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1590 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1591 {"#define USEREFLECTION\n", " reflection"},
1592 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1593 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1594 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1595 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1596 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1597 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1598 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1599 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1600 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1603 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1604 typedef enum shadermode_e
1606 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1607 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1608 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1609 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1610 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1611 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1612 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1613 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1614 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1615 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1616 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1617 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1618 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1623 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1624 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1626 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1627 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1628 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1629 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1630 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1631 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1632 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1633 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1634 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1635 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1636 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1637 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1638 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1641 struct r_glsl_permutation_s;
1642 typedef struct r_glsl_permutation_s
1644 /// hash lookup data
1645 struct r_glsl_permutation_s *hashnext;
1647 unsigned int permutation;
1649 /// indicates if we have tried compiling this permutation already
1651 /// 0 if compilation failed
1653 /// locations of detected uniforms in program object, or -1 if not found
1654 int loc_Texture_First;
1655 int loc_Texture_Second;
1656 int loc_Texture_GammaRamps;
1657 int loc_Texture_Normal;
1658 int loc_Texture_Color;
1659 int loc_Texture_Gloss;
1660 int loc_Texture_Glow;
1661 int loc_Texture_SecondaryNormal;
1662 int loc_Texture_SecondaryColor;
1663 int loc_Texture_SecondaryGloss;
1664 int loc_Texture_SecondaryGlow;
1665 int loc_Texture_Pants;
1666 int loc_Texture_Shirt;
1667 int loc_Texture_FogMask;
1668 int loc_Texture_Lightmap;
1669 int loc_Texture_Deluxemap;
1670 int loc_Texture_Attenuation;
1671 int loc_Texture_Cube;
1672 int loc_Texture_Refraction;
1673 int loc_Texture_Reflection;
1674 int loc_Texture_ShadowMapRect;
1675 int loc_Texture_ShadowMapCube;
1676 int loc_Texture_ShadowMap2D;
1677 int loc_Texture_CubeProjection;
1679 int loc_LightPosition;
1680 int loc_EyePosition;
1681 int loc_Color_Pants;
1682 int loc_Color_Shirt;
1684 int loc_FogPlaneViewDist;
1685 int loc_FogRangeRecip;
1686 int loc_FogHeightFade;
1687 int loc_AmbientScale;
1688 int loc_DiffuseScale;
1689 int loc_SpecularScale;
1690 int loc_SpecularPower;
1692 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1693 int loc_OffsetMapping_Scale;
1695 int loc_AmbientColor;
1696 int loc_DiffuseColor;
1697 int loc_SpecularColor;
1699 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1700 int loc_GammaCoeff; ///< 1 / gamma
1701 int loc_DistortScaleRefractReflect;
1702 int loc_ScreenScaleRefractReflect;
1703 int loc_ScreenCenterRefractReflect;
1704 int loc_RefractColor;
1705 int loc_ReflectColor;
1706 int loc_ReflectFactor;
1707 int loc_ReflectOffset;
1715 int loc_ShadowMap_TextureScale;
1716 int loc_ShadowMap_Parameters;
1718 r_glsl_permutation_t;
1720 #define SHADERPERMUTATION_HASHSIZE 256
1722 /// information about each possible shader permutation
1723 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1724 /// currently selected permutation
1725 r_glsl_permutation_t *r_glsl_permutation;
1726 /// storage for permutations linked in the hash table
1727 memexpandablearray_t r_glsl_permutationarray;
1729 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1731 //unsigned int hashdepth = 0;
1732 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1733 r_glsl_permutation_t *p;
1734 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1736 if (p->mode == mode && p->permutation == permutation)
1738 //if (hashdepth > 10)
1739 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1744 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1746 p->permutation = permutation;
1747 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1748 r_glsl_permutationhash[mode][hashindex] = p;
1749 //if (hashdepth > 10)
1750 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1754 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1757 if (!filename || !filename[0])
1759 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1762 if (printfromdisknotice)
1763 Con_DPrint("from disk... ");
1764 return shaderstring;
1766 else if (!strcmp(filename, "glsl/default.glsl"))
1768 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1769 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1771 return shaderstring;
1774 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1777 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1778 int vertstrings_count = 0;
1779 int geomstrings_count = 0;
1780 int fragstrings_count = 0;
1781 char *vertexstring, *geometrystring, *fragmentstring;
1782 const char *vertstrings_list[32+3];
1783 const char *geomstrings_list[32+3];
1784 const char *fragstrings_list[32+3];
1785 char permutationname[256];
1792 permutationname[0] = 0;
1793 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1794 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1795 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1797 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1799 // the first pretext is which type of shader to compile as
1800 // (later these will all be bound together as a program object)
1801 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1802 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1803 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1805 // the second pretext is the mode (for example a light source)
1806 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1807 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1808 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1809 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1811 // now add all the permutation pretexts
1812 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1814 if (permutation & (1<<i))
1816 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1817 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1818 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1819 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1823 // keep line numbers correct
1824 vertstrings_list[vertstrings_count++] = "\n";
1825 geomstrings_list[geomstrings_count++] = "\n";
1826 fragstrings_list[fragstrings_count++] = "\n";
1830 // now append the shader text itself
1831 vertstrings_list[vertstrings_count++] = vertexstring;
1832 geomstrings_list[geomstrings_count++] = geometrystring;
1833 fragstrings_list[fragstrings_count++] = fragmentstring;
1835 // if any sources were NULL, clear the respective list
1837 vertstrings_count = 0;
1838 if (!geometrystring)
1839 geomstrings_count = 0;
1840 if (!fragmentstring)
1841 fragstrings_count = 0;
1843 // compile the shader program
1844 if (vertstrings_count + geomstrings_count + fragstrings_count)
1845 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1849 qglUseProgramObjectARB(p->program);CHECKGLERROR
1850 // look up all the uniform variable names we care about, so we don't
1851 // have to look them up every time we set them
1852 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1853 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1854 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1855 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1856 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1857 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1858 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1859 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1860 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1861 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1862 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1863 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1864 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1865 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1866 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1867 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1868 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1869 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1870 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1871 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1872 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1873 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1874 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1875 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1876 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1877 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1878 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1879 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1880 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1881 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
1882 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
1883 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1884 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
1885 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1886 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1887 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1888 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1889 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1890 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1891 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1892 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1893 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1894 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1895 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1896 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1897 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1898 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1899 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1900 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1901 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1902 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1903 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1904 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1905 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1906 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1907 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1908 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1909 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1910 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1911 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1912 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1913 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1914 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1915 // initialize the samplers to refer to the texture units we use
1916 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1917 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1918 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1919 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1920 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1921 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1922 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1923 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1924 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1925 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1926 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1927 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1928 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1929 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1930 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1931 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1932 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1933 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1934 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1935 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1936 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1937 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1938 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1939 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1941 if (developer.integer)
1942 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1945 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1949 Mem_Free(vertexstring);
1951 Mem_Free(geometrystring);
1953 Mem_Free(fragmentstring);
1956 void R_GLSL_Restart_f(void)
1958 unsigned int i, limit;
1959 r_glsl_permutation_t *p;
1960 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1961 for (i = 0;i < limit;i++)
1963 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1965 GL_Backend_FreeProgram(p->program);
1966 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1969 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1972 void R_GLSL_DumpShader_f(void)
1976 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1979 Con_Printf("failed to write to glsl/default.glsl\n");
1983 FS_Print(file, "/* The engine may define the following macros:\n");
1984 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1985 for (i = 0;i < SHADERMODE_COUNT;i++)
1986 FS_Print(file, shadermodeinfo[i].pretext);
1987 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1988 FS_Print(file, shaderpermutationinfo[i].pretext);
1989 FS_Print(file, "*/\n");
1990 FS_Print(file, builtinshaderstring);
1993 Con_Printf("glsl/default.glsl written\n");
1996 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1998 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1999 if (r_glsl_permutation != perm)
2001 r_glsl_permutation = perm;
2002 if (!r_glsl_permutation->program)
2004 if (!r_glsl_permutation->compiled)
2005 R_GLSL_CompilePermutation(perm, mode, permutation);
2006 if (!r_glsl_permutation->program)
2008 // remove features until we find a valid permutation
2010 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2012 // reduce i more quickly whenever it would not remove any bits
2013 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2014 if (!(permutation & j))
2017 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2018 if (!r_glsl_permutation->compiled)
2019 R_GLSL_CompilePermutation(perm, mode, permutation);
2020 if (r_glsl_permutation->program)
2023 if (i >= SHADERPERMUTATION_COUNT)
2025 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");
2026 Cvar_SetValueQuick(&r_glsl, 0);
2027 R_GLSL_Restart_f(); // unload shaders
2028 return; // no bit left to clear
2033 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2037 void R_SetupGenericShader(qboolean usetexture)
2039 if (gl_support_fragment_shader)
2041 if (r_glsl.integer && r_glsl_usegeneric.integer)
2042 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2043 else if (r_glsl_permutation)
2045 r_glsl_permutation = NULL;
2046 qglUseProgramObjectARB(0);CHECKGLERROR
2051 void R_SetupGenericTwoTextureShader(int texturemode)
2053 if (gl_support_fragment_shader)
2055 if (r_glsl.integer && r_glsl_usegeneric.integer)
2056 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))));
2057 else if (r_glsl_permutation)
2059 r_glsl_permutation = NULL;
2060 qglUseProgramObjectARB(0);CHECKGLERROR
2063 if (!r_glsl_permutation)
2065 if (texturemode == GL_DECAL && gl_combine.integer)
2066 texturemode = GL_INTERPOLATE_ARB;
2067 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
2071 void R_SetupDepthOrShadowShader(void)
2073 if (gl_support_fragment_shader)
2075 if (r_glsl.integer && r_glsl_usegeneric.integer)
2076 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2077 else if (r_glsl_permutation)
2079 r_glsl_permutation = NULL;
2080 qglUseProgramObjectARB(0);CHECKGLERROR
2085 void R_SetupShowDepthShader(void)
2087 if (gl_support_fragment_shader)
2089 if (r_glsl.integer && r_glsl_usegeneric.integer)
2090 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2091 else if (r_glsl_permutation)
2093 r_glsl_permutation = NULL;
2094 qglUseProgramObjectARB(0);CHECKGLERROR
2099 extern rtexture_t *r_shadow_attenuationgradienttexture;
2100 extern rtexture_t *r_shadow_attenuation2dtexture;
2101 extern rtexture_t *r_shadow_attenuation3dtexture;
2102 extern qboolean r_shadow_usingshadowmaprect;
2103 extern qboolean r_shadow_usingshadowmapcube;
2104 extern qboolean r_shadow_usingshadowmap2d;
2105 extern float r_shadow_shadowmap_texturescale[2];
2106 extern float r_shadow_shadowmap_parameters[4];
2107 extern qboolean r_shadow_shadowmapvsdct;
2108 extern qboolean r_shadow_shadowmapsampler;
2109 extern int r_shadow_shadowmappcf;
2110 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2112 // select a permutation of the lighting shader appropriate to this
2113 // combination of texture, entity, light source, and fogging, only use the
2114 // minimum features necessary to avoid wasting rendering time in the
2115 // fragment shader on features that are not being used
2116 unsigned int permutation = 0;
2117 unsigned int mode = 0;
2118 // TODO: implement geometry-shader based shadow volumes someday
2119 if (r_glsl_offsetmapping.integer)
2121 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2122 if (r_glsl_offsetmapping_reliefmapping.integer)
2123 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2125 if (rsurfacepass == RSURFPASS_BACKGROUND)
2127 // distorted background
2128 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2129 mode = SHADERMODE_WATER;
2131 mode = SHADERMODE_REFRACTION;
2133 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2136 mode = SHADERMODE_LIGHTSOURCE;
2137 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2138 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2139 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2140 permutation |= SHADERPERMUTATION_CUBEFILTER;
2141 if (diffusescale > 0)
2142 permutation |= SHADERPERMUTATION_DIFFUSE;
2143 if (specularscale > 0)
2144 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2145 if (r_refdef.fogenabled)
2146 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2147 if (rsurface.texture->colormapping)
2148 permutation |= SHADERPERMUTATION_COLORMAPPING;
2149 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2151 if (r_shadow_usingshadowmaprect)
2152 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2153 if (r_shadow_usingshadowmap2d)
2154 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2155 if (r_shadow_usingshadowmapcube)
2156 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2157 else if(r_shadow_shadowmapvsdct)
2158 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2160 if (r_shadow_shadowmapsampler)
2161 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2162 if (r_shadow_shadowmappcf > 1)
2163 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2164 else if (r_shadow_shadowmappcf)
2165 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2168 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2170 // unshaded geometry (fullbright or ambient model lighting)
2171 mode = SHADERMODE_FLATCOLOR;
2172 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2173 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2174 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2175 permutation |= SHADERPERMUTATION_GLOW;
2176 if (r_refdef.fogenabled)
2177 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2178 if (rsurface.texture->colormapping)
2179 permutation |= SHADERPERMUTATION_COLORMAPPING;
2180 if (r_glsl_offsetmapping.integer)
2182 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2183 if (r_glsl_offsetmapping_reliefmapping.integer)
2184 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2186 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2187 permutation |= SHADERPERMUTATION_REFLECTION;
2189 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2191 // directional model lighting
2192 mode = SHADERMODE_LIGHTDIRECTION;
2193 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2194 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2195 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2196 permutation |= SHADERPERMUTATION_GLOW;
2197 permutation |= SHADERPERMUTATION_DIFFUSE;
2198 if (specularscale > 0)
2199 permutation |= SHADERPERMUTATION_SPECULAR;
2200 if (r_refdef.fogenabled)
2201 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2202 if (rsurface.texture->colormapping)
2203 permutation |= SHADERPERMUTATION_COLORMAPPING;
2204 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2205 permutation |= SHADERPERMUTATION_REFLECTION;
2207 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2209 // ambient model lighting
2210 mode = SHADERMODE_LIGHTDIRECTION;
2211 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2212 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2213 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2214 permutation |= SHADERPERMUTATION_GLOW;
2215 if (r_refdef.fogenabled)
2216 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2217 if (rsurface.texture->colormapping)
2218 permutation |= SHADERPERMUTATION_COLORMAPPING;
2219 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2220 permutation |= SHADERPERMUTATION_REFLECTION;
2225 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2227 // deluxemapping (light direction texture)
2228 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2229 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2231 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2232 permutation |= SHADERPERMUTATION_DIFFUSE;
2233 if (specularscale > 0)
2234 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2236 else if (r_glsl_deluxemapping.integer >= 2)
2238 // fake deluxemapping (uniform light direction in tangentspace)
2239 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2240 permutation |= SHADERPERMUTATION_DIFFUSE;
2241 if (specularscale > 0)
2242 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2244 else if (rsurface.uselightmaptexture)
2246 // ordinary lightmapping (q1bsp, q3bsp)
2247 mode = SHADERMODE_LIGHTMAP;
2251 // ordinary vertex coloring (q3bsp)
2252 mode = SHADERMODE_VERTEXCOLOR;
2254 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2255 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2256 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2257 permutation |= SHADERPERMUTATION_GLOW;
2258 if (r_refdef.fogenabled)
2259 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2260 if (rsurface.texture->colormapping)
2261 permutation |= SHADERPERMUTATION_COLORMAPPING;
2262 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2263 permutation |= SHADERPERMUTATION_REFLECTION;
2265 if(permutation & SHADERPERMUTATION_SPECULAR)
2266 if(r_shadow_glossexact.integer)
2267 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2268 R_SetupShader_SetPermutation(mode, permutation);
2269 if (mode == SHADERMODE_LIGHTSOURCE)
2271 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2272 if (permutation & SHADERPERMUTATION_DIFFUSE)
2274 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2275 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2276 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2277 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2281 // ambient only is simpler
2282 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]);
2283 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2284 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2285 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2287 // additive passes are only darkened by fog, not tinted
2288 if (r_glsl_permutation->loc_FogColor >= 0)
2289 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2290 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2291 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]);
2295 if (mode == SHADERMODE_LIGHTDIRECTION)
2297 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);
2298 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);
2299 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);
2300 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]);
2304 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2305 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2306 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2308 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]);
2309 if (r_glsl_permutation->loc_GlowColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_GlowColor, rsurface.glowmod[0] * r_hdr_glowintensity.value, rsurface.glowmod[1] * r_hdr_glowintensity.value, rsurface.glowmod[2] * r_hdr_glowintensity.value);
2310 // additive passes are only darkened by fog, not tinted
2311 if (r_glsl_permutation->loc_FogColor >= 0)
2313 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2314 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2316 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2318 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);
2319 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]);
2320 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]);
2321 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2322 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2323 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2324 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2326 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2327 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2328 if (r_glsl_permutation->loc_Color_Pants >= 0)
2330 if (rsurface.texture->currentskinframe->pants)
2331 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2333 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2335 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2337 if (rsurface.texture->currentskinframe->shirt)
2338 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2340 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2342 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2343 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2344 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2345 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2346 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2348 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2352 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2354 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2358 #define SKINFRAME_HASH 1024
2362 int loadsequence; // incremented each level change
2363 memexpandablearray_t array;
2364 skinframe_t *hash[SKINFRAME_HASH];
2367 r_skinframe_t r_skinframe;
2369 void R_SkinFrame_PrepareForPurge(void)
2371 r_skinframe.loadsequence++;
2372 // wrap it without hitting zero
2373 if (r_skinframe.loadsequence >= 200)
2374 r_skinframe.loadsequence = 1;
2377 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2381 // mark the skinframe as used for the purging code
2382 skinframe->loadsequence = r_skinframe.loadsequence;
2385 void R_SkinFrame_Purge(void)
2389 for (i = 0;i < SKINFRAME_HASH;i++)
2391 for (s = r_skinframe.hash[i];s;s = s->next)
2393 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2395 if (s->merged == s->base)
2397 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2398 R_PurgeTexture(s->stain );s->stain = NULL;
2399 R_PurgeTexture(s->merged);s->merged = NULL;
2400 R_PurgeTexture(s->base );s->base = NULL;
2401 R_PurgeTexture(s->pants );s->pants = NULL;
2402 R_PurgeTexture(s->shirt );s->shirt = NULL;
2403 R_PurgeTexture(s->nmap );s->nmap = NULL;
2404 R_PurgeTexture(s->gloss );s->gloss = NULL;
2405 R_PurgeTexture(s->glow );s->glow = NULL;
2406 R_PurgeTexture(s->fog );s->fog = NULL;
2407 s->loadsequence = 0;
2413 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2415 char basename[MAX_QPATH];
2417 Image_StripImageExtension(name, basename, sizeof(basename));
2419 if( last == NULL ) {
2421 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2422 item = r_skinframe.hash[hashindex];
2427 // linearly search through the hash bucket
2428 for( ; item ; item = item->next ) {
2429 if( !strcmp( item->basename, basename ) ) {
2436 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2440 char basename[MAX_QPATH];
2442 Image_StripImageExtension(name, basename, sizeof(basename));
2444 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2445 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2446 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2450 rtexture_t *dyntexture;
2451 // check whether its a dynamic texture
2452 dyntexture = CL_GetDynTexture( basename );
2453 if (!add && !dyntexture)
2455 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2456 memset(item, 0, sizeof(*item));
2457 strlcpy(item->basename, basename, sizeof(item->basename));
2458 item->base = dyntexture; // either NULL or dyntexture handle
2459 item->textureflags = textureflags;
2460 item->comparewidth = comparewidth;
2461 item->compareheight = compareheight;
2462 item->comparecrc = comparecrc;
2463 item->next = r_skinframe.hash[hashindex];
2464 r_skinframe.hash[hashindex] = item;
2466 else if( item->base == NULL )
2468 rtexture_t *dyntexture;
2469 // check whether its a dynamic texture
2470 // 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]
2471 dyntexture = CL_GetDynTexture( basename );
2472 item->base = dyntexture; // either NULL or dyntexture handle
2475 R_SkinFrame_MarkUsed(item);
2479 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2481 unsigned long long avgcolor[5], wsum; \
2489 for(pix = 0; pix < cnt; ++pix) \
2492 for(comp = 0; comp < 3; ++comp) \
2494 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2497 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2499 for(comp = 0; comp < 3; ++comp) \
2500 avgcolor[comp] += getpixel * w; \
2503 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2504 avgcolor[4] += getpixel; \
2506 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2508 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2509 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2510 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2511 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2514 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2516 // FIXME: it should be possible to disable loading various layers using
2517 // cvars, to prevent wasted loading time and memory usage if the user does
2519 qboolean loadnormalmap = true;
2520 qboolean loadgloss = true;
2521 qboolean loadpantsandshirt = true;
2522 qboolean loadglow = true;
2524 unsigned char *pixels;
2525 unsigned char *bumppixels;
2526 unsigned char *basepixels = NULL;
2527 int basepixels_width;
2528 int basepixels_height;
2529 skinframe_t *skinframe;
2534 if (cls.state == ca_dedicated)
2537 // return an existing skinframe if already loaded
2538 // if loading of the first image fails, don't make a new skinframe as it
2539 // would cause all future lookups of this to be missing
2540 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2541 if (skinframe && skinframe->base)
2544 basepixels = loadimagepixelsbgra(name, complain, true);
2545 if (basepixels == NULL)
2548 if (developer_loading.integer)
2549 Con_Printf("loading skin \"%s\"\n", name);
2551 // we've got some pixels to store, so really allocate this new texture now
2553 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2554 skinframe->stain = NULL;
2555 skinframe->merged = NULL;
2556 skinframe->base = r_texture_notexture;
2557 skinframe->pants = NULL;
2558 skinframe->shirt = NULL;
2559 skinframe->nmap = r_texture_blanknormalmap;
2560 skinframe->gloss = NULL;
2561 skinframe->glow = NULL;
2562 skinframe->fog = NULL;
2564 basepixels_width = image_width;
2565 basepixels_height = image_height;
2566 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);
2568 if (textureflags & TEXF_ALPHA)
2570 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2571 if (basepixels[j] < 255)
2573 if (j < basepixels_width * basepixels_height * 4)
2575 // has transparent pixels
2578 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2579 for (j = 0;j < image_width * image_height * 4;j += 4)
2584 pixels[j+3] = basepixels[j+3];
2586 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);
2591 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2592 //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]);
2594 // _norm is the name used by tenebrae and has been adopted as standard
2597 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2599 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);
2603 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2605 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2606 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2607 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);
2609 Mem_Free(bumppixels);
2611 else if (r_shadow_bumpscale_basetexture.value > 0)
2613 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2614 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2615 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);
2619 // _luma is supported for tenebrae compatibility
2620 // (I think it's a very stupid name, but oh well)
2621 // _glow is the preferred name
2622 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;}
2623 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;}
2624 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;}
2625 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;}
2628 Mem_Free(basepixels);
2633 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2635 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, NULL);
2638 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)
2643 for (i = 0;i < width*height;i++)
2644 if (((unsigned char *)&palette[in[i]])[3] > 0)
2646 if (i == width*height)
2649 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2652 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2653 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2656 unsigned char *temp1, *temp2;
2657 skinframe_t *skinframe;
2659 if (cls.state == ca_dedicated)
2662 // if already loaded just return it, otherwise make a new skinframe
2663 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2664 if (skinframe && skinframe->base)
2667 skinframe->stain = NULL;
2668 skinframe->merged = NULL;
2669 skinframe->base = r_texture_notexture;
2670 skinframe->pants = NULL;
2671 skinframe->shirt = NULL;
2672 skinframe->nmap = r_texture_blanknormalmap;
2673 skinframe->gloss = NULL;
2674 skinframe->glow = NULL;
2675 skinframe->fog = NULL;
2677 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2681 if (developer_loading.integer)
2682 Con_Printf("loading 32bit skin \"%s\"\n", name);
2684 if (r_shadow_bumpscale_basetexture.value > 0)
2686 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2687 temp2 = temp1 + width * height * 4;
2688 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2689 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2692 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2693 if (textureflags & TEXF_ALPHA)
2695 for (i = 3;i < width * height * 4;i += 4)
2696 if (skindata[i] < 255)
2698 if (i < width * height * 4)
2700 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2701 memcpy(fogpixels, skindata, width * height * 4);
2702 for (i = 0;i < width * height * 4;i += 4)
2703 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2704 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2705 Mem_Free(fogpixels);
2709 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2710 //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]);
2715 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2718 unsigned char *temp1, *temp2;
2719 unsigned int *palette;
2720 skinframe_t *skinframe;
2722 if (cls.state == ca_dedicated)
2725 // if already loaded just return it, otherwise make a new skinframe
2726 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2727 if (skinframe && skinframe->base)
2730 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2732 skinframe->stain = NULL;
2733 skinframe->merged = NULL;
2734 skinframe->base = r_texture_notexture;
2735 skinframe->pants = NULL;
2736 skinframe->shirt = NULL;
2737 skinframe->nmap = r_texture_blanknormalmap;
2738 skinframe->gloss = NULL;
2739 skinframe->glow = NULL;
2740 skinframe->fog = NULL;
2742 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2746 if (developer_loading.integer)
2747 Con_Printf("loading quake skin \"%s\"\n", name);
2749 if (r_shadow_bumpscale_basetexture.value > 0)
2751 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2752 temp2 = temp1 + width * height * 4;
2753 // use either a custom palette or the quake palette
2754 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2755 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2756 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2759 // use either a custom palette, or the quake palette
2760 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2761 if (loadglowtexture)
2762 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2763 if (loadpantsandshirt)
2765 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2766 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2768 if (skinframe->pants || skinframe->shirt)
2769 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
2770 if (textureflags & TEXF_ALPHA)
2772 for (i = 0;i < width * height;i++)
2773 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2775 if (i < width * height)
2776 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2779 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2780 //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]);
2785 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
2788 skinframe_t *skinframe;
2790 if (cls.state == ca_dedicated)
2793 // if already loaded just return it, otherwise make a new skinframe
2794 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2795 if (skinframe && skinframe->base)
2798 skinframe->stain = NULL;
2799 skinframe->merged = NULL;
2800 skinframe->base = r_texture_notexture;
2801 skinframe->pants = NULL;
2802 skinframe->shirt = NULL;
2803 skinframe->nmap = r_texture_blanknormalmap;
2804 skinframe->gloss = NULL;
2805 skinframe->glow = NULL;
2806 skinframe->fog = NULL;
2808 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2812 if (developer_loading.integer)
2813 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2815 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, skinframe->basename, palette, skinframe->textureflags, true);
2816 if (textureflags & TEXF_ALPHA)
2818 for (i = 0;i < width * height;i++)
2819 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
2821 if (i < width * height)
2822 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
2825 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2826 //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]);
2831 skinframe_t *R_SkinFrame_LoadMissing(void)
2833 skinframe_t *skinframe;
2835 if (cls.state == ca_dedicated)
2838 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2839 skinframe->stain = NULL;
2840 skinframe->merged = NULL;
2841 skinframe->base = r_texture_notexture;
2842 skinframe->pants = NULL;
2843 skinframe->shirt = NULL;
2844 skinframe->nmap = r_texture_blanknormalmap;
2845 skinframe->gloss = NULL;
2846 skinframe->glow = NULL;
2847 skinframe->fog = NULL;
2849 skinframe->avgcolor[0] = rand() / RAND_MAX;
2850 skinframe->avgcolor[1] = rand() / RAND_MAX;
2851 skinframe->avgcolor[2] = rand() / RAND_MAX;
2852 skinframe->avgcolor[3] = 1;
2857 void R_Main_FreeViewCache(void)
2859 if (r_refdef.viewcache.entityvisible)
2860 Mem_Free(r_refdef.viewcache.entityvisible);
2861 if (r_refdef.viewcache.world_pvsbits)
2862 Mem_Free(r_refdef.viewcache.world_pvsbits);
2863 if (r_refdef.viewcache.world_leafvisible)
2864 Mem_Free(r_refdef.viewcache.world_leafvisible);
2865 if (r_refdef.viewcache.world_surfacevisible)
2866 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2867 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2870 void R_Main_ResizeViewCache(void)
2872 int numentities = r_refdef.scene.numentities;
2873 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
2874 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
2875 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
2876 if (r_refdef.viewcache.maxentities < numentities)
2878 r_refdef.viewcache.maxentities = numentities;
2879 if (r_refdef.viewcache.entityvisible)
2880 Mem_Free(r_refdef.viewcache.entityvisible);
2881 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
2883 if (r_refdef.viewcache.world_numclusters != numclusters)
2885 r_refdef.viewcache.world_numclusters = numclusters;
2886 if (r_refdef.viewcache.world_pvsbits)
2887 Mem_Free(r_refdef.viewcache.world_pvsbits);
2888 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, (r_refdef.viewcache.world_numclusters+7)>>3);
2890 if (r_refdef.viewcache.world_numleafs != numleafs)
2892 r_refdef.viewcache.world_numleafs = numleafs;
2893 if (r_refdef.viewcache.world_leafvisible)
2894 Mem_Free(r_refdef.viewcache.world_leafvisible);
2895 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
2897 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
2899 r_refdef.viewcache.world_numsurfaces = numsurfaces;
2900 if (r_refdef.viewcache.world_surfacevisible)
2901 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2902 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
2906 void gl_main_start(void)
2910 memset(r_queries, 0, sizeof(r_queries));
2912 r_qwskincache = NULL;
2913 r_qwskincache_size = 0;
2915 // set up r_skinframe loading system for textures
2916 memset(&r_skinframe, 0, sizeof(r_skinframe));
2917 r_skinframe.loadsequence = 1;
2918 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2920 r_main_texturepool = R_AllocTexturePool();
2921 R_BuildBlankTextures();
2923 if (gl_texturecubemap)
2926 R_BuildNormalizationCube();
2928 r_texture_fogattenuation = NULL;
2929 r_texture_gammaramps = NULL;
2930 //r_texture_fogintensity = NULL;
2931 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2932 memset(&r_waterstate, 0, sizeof(r_waterstate));
2933 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2934 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2935 memset(&r_svbsp, 0, sizeof (r_svbsp));
2937 r_refdef.fogmasktable_density = 0;
2940 extern rtexture_t *loadingscreentexture;
2941 void gl_main_shutdown(void)
2943 R_Main_FreeViewCache();
2946 qglDeleteQueriesARB(r_maxqueries, r_queries);
2950 memset(r_queries, 0, sizeof(r_queries));
2952 r_qwskincache = NULL;
2953 r_qwskincache_size = 0;
2955 // clear out the r_skinframe state
2956 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2957 memset(&r_skinframe, 0, sizeof(r_skinframe));
2960 Mem_Free(r_svbsp.nodes);
2961 memset(&r_svbsp, 0, sizeof (r_svbsp));
2962 R_FreeTexturePool(&r_main_texturepool);
2963 loadingscreentexture = NULL;
2964 r_texture_blanknormalmap = NULL;
2965 r_texture_white = NULL;
2966 r_texture_grey128 = NULL;
2967 r_texture_black = NULL;
2968 r_texture_whitecube = NULL;
2969 r_texture_normalizationcube = NULL;
2970 r_texture_fogattenuation = NULL;
2971 r_texture_gammaramps = NULL;
2972 //r_texture_fogintensity = NULL;
2973 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2974 memset(&r_waterstate, 0, sizeof(r_waterstate));
2978 extern void CL_ParseEntityLump(char *entitystring);
2979 void gl_main_newmap(void)
2981 // FIXME: move this code to client
2983 char *entities, entname[MAX_QPATH];
2985 Mem_Free(r_qwskincache);
2986 r_qwskincache = NULL;
2987 r_qwskincache_size = 0;
2990 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2991 l = (int)strlen(entname) - 4;
2992 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2994 memcpy(entname + l, ".ent", 5);
2995 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2997 CL_ParseEntityLump(entities);
3002 if (cl.worldmodel->brush.entities)
3003 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3005 R_Main_FreeViewCache();
3008 void GL_Main_Init(void)
3010 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3012 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3013 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3014 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3015 if (gamemode == GAME_NEHAHRA)
3017 Cvar_RegisterVariable (&gl_fogenable);
3018 Cvar_RegisterVariable (&gl_fogdensity);
3019 Cvar_RegisterVariable (&gl_fogred);
3020 Cvar_RegisterVariable (&gl_foggreen);
3021 Cvar_RegisterVariable (&gl_fogblue);
3022 Cvar_RegisterVariable (&gl_fogstart);
3023 Cvar_RegisterVariable (&gl_fogend);
3024 Cvar_RegisterVariable (&gl_skyclip);
3026 Cvar_RegisterVariable(&r_motionblur);
3027 Cvar_RegisterVariable(&r_motionblur_maxblur);
3028 Cvar_RegisterVariable(&r_motionblur_bmin);
3029 Cvar_RegisterVariable(&r_motionblur_vmin);
3030 Cvar_RegisterVariable(&r_motionblur_vmax);
3031 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3032 Cvar_RegisterVariable(&r_motionblur_randomize);
3033 Cvar_RegisterVariable(&r_damageblur);
3034 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3035 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3036 Cvar_RegisterVariable(&r_equalize_entities_by);
3037 Cvar_RegisterVariable(&r_equalize_entities_to);
3038 Cvar_RegisterVariable(&r_animcache);
3039 Cvar_RegisterVariable(&r_depthfirst);
3040 Cvar_RegisterVariable(&r_useinfinitefarclip);
3041 Cvar_RegisterVariable(&r_farclip_base);
3042 Cvar_RegisterVariable(&r_farclip_world);
3043 Cvar_RegisterVariable(&r_nearclip);
3044 Cvar_RegisterVariable(&r_showbboxes);
3045 Cvar_RegisterVariable(&r_showsurfaces);
3046 Cvar_RegisterVariable(&r_showtris);
3047 Cvar_RegisterVariable(&r_shownormals);
3048 Cvar_RegisterVariable(&r_showlighting);
3049 Cvar_RegisterVariable(&r_showshadowvolumes);
3050 Cvar_RegisterVariable(&r_showcollisionbrushes);
3051 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3052 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3053 Cvar_RegisterVariable(&r_showdisabledepthtest);
3054 Cvar_RegisterVariable(&r_drawportals);
3055 Cvar_RegisterVariable(&r_drawentities);
3056 Cvar_RegisterVariable(&r_cullentities_trace);
3057 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3058 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3059 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3060 Cvar_RegisterVariable(&r_drawviewmodel);
3061 Cvar_RegisterVariable(&r_speeds);
3062 Cvar_RegisterVariable(&r_fullbrights);
3063 Cvar_RegisterVariable(&r_wateralpha);
3064 Cvar_RegisterVariable(&r_dynamic);
3065 Cvar_RegisterVariable(&r_fullbright);
3066 Cvar_RegisterVariable(&r_shadows);
3067 Cvar_RegisterVariable(&r_shadows_darken);
3068 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3069 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3070 Cvar_RegisterVariable(&r_shadows_throwdistance);
3071 Cvar_RegisterVariable(&r_shadows_throwdirection);
3072 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3073 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3074 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3075 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3076 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3077 Cvar_RegisterVariable(&r_fog_exp2);
3078 Cvar_RegisterVariable(&r_drawfog);
3079 Cvar_RegisterVariable(&r_textureunits);
3080 Cvar_RegisterVariable(&r_glsl);
3081 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3082 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3083 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3084 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3085 Cvar_RegisterVariable(&r_glsl_postprocess);
3086 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3087 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3088 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3089 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3090 Cvar_RegisterVariable(&r_glsl_usegeneric);
3091 Cvar_RegisterVariable(&r_water);
3092 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3093 Cvar_RegisterVariable(&r_water_clippingplanebias);
3094 Cvar_RegisterVariable(&r_water_refractdistort);
3095 Cvar_RegisterVariable(&r_water_reflectdistort);
3096 Cvar_RegisterVariable(&r_lerpsprites);
3097 Cvar_RegisterVariable(&r_lerpmodels);
3098 Cvar_RegisterVariable(&r_lerplightstyles);
3099 Cvar_RegisterVariable(&r_waterscroll);
3100 Cvar_RegisterVariable(&r_bloom);
3101 Cvar_RegisterVariable(&r_bloom_colorscale);
3102 Cvar_RegisterVariable(&r_bloom_brighten);
3103 Cvar_RegisterVariable(&r_bloom_blur);
3104 Cvar_RegisterVariable(&r_bloom_resolution);
3105 Cvar_RegisterVariable(&r_bloom_colorexponent);
3106 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3107 Cvar_RegisterVariable(&r_hdr);
3108 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3109 Cvar_RegisterVariable(&r_hdr_glowintensity);
3110 Cvar_RegisterVariable(&r_hdr_range);
3111 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3112 Cvar_RegisterVariable(&developer_texturelogging);
3113 Cvar_RegisterVariable(&gl_lightmaps);
3114 Cvar_RegisterVariable(&r_test);
3115 Cvar_RegisterVariable(&r_batchmode);
3116 Cvar_RegisterVariable(&r_glsl_saturation);
3117 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3118 Cvar_SetValue("r_fullbrights", 0);
3119 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3121 Cvar_RegisterVariable(&r_track_sprites);
3122 Cvar_RegisterVariable(&r_track_sprites_flags);
3123 Cvar_RegisterVariable(&r_track_sprites_scalew);
3124 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3127 extern void R_Textures_Init(void);
3128 extern void GL_Draw_Init(void);
3129 extern void GL_Main_Init(void);
3130 extern void R_Shadow_Init(void);
3131 extern void R_Sky_Init(void);
3132 extern void GL_Surf_Init(void);
3133 extern void R_Particles_Init(void);
3134 extern void R_Explosion_Init(void);
3135 extern void gl_backend_init(void);
3136 extern void Sbar_Init(void);
3137 extern void R_LightningBeams_Init(void);
3138 extern void Mod_RenderInit(void);
3140 void Render_Init(void)
3152 R_LightningBeams_Init();
3161 extern char *ENGINE_EXTENSIONS;
3164 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3165 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3166 gl_version = (const char *)qglGetString(GL_VERSION);
3167 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3171 if (!gl_platformextensions)
3172 gl_platformextensions = "";
3174 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3175 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3176 Con_Printf("GL_VERSION: %s\n", gl_version);
3177 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3178 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3180 VID_CheckExtensions();
3182 // LordHavoc: report supported extensions
3183 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3185 // clear to black (loading plaque will be seen over this)
3187 qglClearColor(0,0,0,1);CHECKGLERROR
3188 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3191 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3195 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3197 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3200 p = r_refdef.view.frustum + i;
3205 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3209 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3213 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3217 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3221 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3225 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3229 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3233 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3241 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3245 for (i = 0;i < numplanes;i++)
3252 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3256 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3260 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3264 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3268 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3272 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3276 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3280 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3288 //==================================================================================
3290 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3293 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3294 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3295 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3298 typedef struct r_animcache_entity_s
3305 qboolean wantnormals;
3306 qboolean wanttangents;
3308 r_animcache_entity_t;
3310 typedef struct r_animcache_s
3312 r_animcache_entity_t entity[MAX_EDICTS];
3318 static r_animcache_t r_animcachestate;
3320 void R_AnimCache_Free(void)
3323 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3325 r_animcachestate.entity[idx].maxvertices = 0;
3326 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3327 r_animcachestate.entity[idx].vertex3f = NULL;
3328 r_animcachestate.entity[idx].normal3f = NULL;
3329 r_animcachestate.entity[idx].svector3f = NULL;
3330 r_animcachestate.entity[idx].tvector3f = NULL;
3332 r_animcachestate.currentindex = 0;
3333 r_animcachestate.maxindex = 0;
3336 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3340 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3342 if (cache->maxvertices >= numvertices)
3345 // Release existing memory
3346 if (cache->vertex3f)
3347 Mem_Free(cache->vertex3f);
3349 // Pad by 1024 verts
3350 cache->maxvertices = (numvertices + 1023) & ~1023;
3351 arraySize = cache->maxvertices * 3;
3353 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3354 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3355 r_animcachestate.entity[cacheIdx].vertex3f = base;
3356 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3357 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3358 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3360 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3363 void R_AnimCache_NewFrame(void)
3367 if (r_animcache.integer && r_drawentities.integer)
3368 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3369 else if (r_animcachestate.maxindex)
3372 r_animcachestate.currentindex = 0;
3374 for (i = 0;i < r_refdef.scene.numentities;i++)
3375 r_refdef.scene.entities[i]->animcacheindex = -1;
3378 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3380 dp_model_t *model = ent->model;
3381 r_animcache_entity_t *c;
3382 // see if it's already cached this frame
3383 if (ent->animcacheindex >= 0)
3385 // add normals/tangents if needed
3386 c = r_animcachestate.entity + ent->animcacheindex;
3388 wantnormals = false;
3389 if (c->wanttangents)
3390 wanttangents = false;
3391 if (wantnormals || wanttangents)
3392 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3396 // see if this ent is worth caching
3397 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3399 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3401 // assign it a cache entry and make sure the arrays are big enough
3402 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3403 ent->animcacheindex = r_animcachestate.currentindex++;
3404 c = r_animcachestate.entity + ent->animcacheindex;
3405 c->wantnormals = wantnormals;
3406 c->wanttangents = wanttangents;
3407 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3412 void R_AnimCache_CacheVisibleEntities(void)
3415 qboolean wantnormals;
3416 qboolean wanttangents;
3418 if (!r_animcachestate.maxindex)
3421 wantnormals = !r_showsurfaces.integer;
3422 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3424 // TODO: thread this?
3426 for (i = 0;i < r_refdef.scene.numentities;i++)
3428 if (!r_refdef.viewcache.entityvisible[i])
3430 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3434 //==================================================================================
3436 static void R_View_UpdateEntityLighting (void)
3439 entity_render_t *ent;
3440 vec3_t tempdiffusenormal, avg;
3441 vec_t f, fa, fd, fdd;
3443 for (i = 0;i < r_refdef.scene.numentities;i++)
3445 ent = r_refdef.scene.entities[i];
3447 // skip unseen models
3448 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3452 if (ent->model && ent->model->brush.num_leafs)
3454 // TODO: use modellight for r_ambient settings on world?
3455 VectorSet(ent->modellight_ambient, 0, 0, 0);
3456 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3457 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3461 // fetch the lighting from the worldmodel data
3462 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));
3463 VectorClear(ent->modellight_diffuse);
3464 VectorClear(tempdiffusenormal);
3465 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3468 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3469 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3470 if(ent->flags & RENDER_EQUALIZE)
3472 // first fix up ambient lighting...
3473 if(r_equalize_entities_minambient.value > 0)
3475 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3478 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3479 if(fa < r_equalize_entities_minambient.value * fd)
3482 // fa'/fd' = minambient
3483 // fa'+0.25*fd' = fa+0.25*fd
3485 // fa' = fd' * minambient
3486 // fd'*(0.25+minambient) = fa+0.25*fd
3488 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3489 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3491 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3492 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
3493 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3494 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3499 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3501 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3502 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3505 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3506 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3507 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3513 VectorSet(ent->modellight_ambient, 1, 1, 1);
3515 // move the light direction into modelspace coordinates for lighting code
3516 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3517 if(VectorLength2(ent->modellight_lightdir) == 0)
3518 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3519 VectorNormalize(ent->modellight_lightdir);
3523 #define MAX_LINEOFSIGHTTRACES 64
3525 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3528 vec3_t boxmins, boxmaxs;
3531 dp_model_t *model = r_refdef.scene.worldmodel;
3533 if (!model || !model->brush.TraceLineOfSight)
3536 // expand the box a little
3537 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3538 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3539 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3540 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3541 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3542 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3545 VectorCopy(eye, start);
3546 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3547 if (model->brush.TraceLineOfSight(model, start, end))
3550 // try various random positions
3551 for (i = 0;i < numsamples;i++)
3553 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3554 if (model->brush.TraceLineOfSight(model, start, end))
3562 static void R_View_UpdateEntityVisible (void)
3565 entity_render_t *ent;
3567 if (!r_drawentities.integer)
3570 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3571 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3573 // worldmodel can check visibility
3574 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3575 for (i = 0;i < r_refdef.scene.numentities;i++)
3577 ent = r_refdef.scene.entities[i];
3578 if (!(ent->flags & renderimask))
3579 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)))
3580 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
3581 r_refdef.viewcache.entityvisible[i] = true;
3583 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3585 for (i = 0;i < r_refdef.scene.numentities;i++)
3587 ent = r_refdef.scene.entities[i];
3588 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3590 if(R_CanSeeBox(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3591 ent->last_trace_visibility = realtime;
3592 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3593 r_refdef.viewcache.entityvisible[i] = 0;
3600 // no worldmodel or it can't check visibility
3601 for (i = 0;i < r_refdef.scene.numentities;i++)
3603 ent = r_refdef.scene.entities[i];
3604 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));
3609 /// only used if skyrendermasked, and normally returns false
3610 int R_DrawBrushModelsSky (void)
3613 entity_render_t *ent;
3615 if (!r_drawentities.integer)
3619 for (i = 0;i < r_refdef.scene.numentities;i++)
3621 if (!r_refdef.viewcache.entityvisible[i])
3623 ent = r_refdef.scene.entities[i];
3624 if (!ent->model || !ent->model->DrawSky)
3626 ent->model->DrawSky(ent);
3632 static void R_DrawNoModel(entity_render_t *ent);
3633 static void R_DrawModels(void)
3636 entity_render_t *ent;
3638 if (!r_drawentities.integer)
3641 for (i = 0;i < r_refdef.scene.numentities;i++)
3643 if (!r_refdef.viewcache.entityvisible[i])
3645 ent = r_refdef.scene.entities[i];
3646 r_refdef.stats.entities++;
3647 if (ent->model && ent->model->Draw != NULL)
3648 ent->model->Draw(ent);
3654 static void R_DrawModelsDepth(void)
3657 entity_render_t *ent;
3659 if (!r_drawentities.integer)
3662 for (i = 0;i < r_refdef.scene.numentities;i++)
3664 if (!r_refdef.viewcache.entityvisible[i])
3666 ent = r_refdef.scene.entities[i];
3667 if (ent->model && ent->model->DrawDepth != NULL)
3668 ent->model->DrawDepth(ent);
3672 static void R_DrawModelsDebug(void)
3675 entity_render_t *ent;
3677 if (!r_drawentities.integer)
3680 for (i = 0;i < r_refdef.scene.numentities;i++)
3682 if (!r_refdef.viewcache.entityvisible[i])
3684 ent = r_refdef.scene.entities[i];
3685 if (ent->model && ent->model->DrawDebug != NULL)
3686 ent->model->DrawDebug(ent);
3690 static void R_DrawModelsAddWaterPlanes(void)
3693 entity_render_t *ent;
3695 if (!r_drawentities.integer)
3698 for (i = 0;i < r_refdef.scene.numentities;i++)
3700 if (!r_refdef.viewcache.entityvisible[i])
3702 ent = r_refdef.scene.entities[i];
3703 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3704 ent->model->DrawAddWaterPlanes(ent);
3708 static void R_DrawModelDecals_Entity(entity_render_t *ent);
3709 static void R_DrawModelDecals(void)
3712 entity_render_t *ent;
3714 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
3716 if (!r_drawentities.integer || r_showsurfaces.integer)
3719 for (i = 0;i < r_refdef.scene.numentities;i++)
3721 if (!r_refdef.viewcache.entityvisible[i])
3723 ent = r_refdef.scene.entities[i];
3724 r_refdef.stats.entities++;
3725 if (ent->decalsystem.numdecals)
3726 R_DrawModelDecals_Entity(ent);
3730 static void R_View_SetFrustum(void)
3733 double slopex, slopey;
3734 vec3_t forward, left, up, origin;
3736 // we can't trust r_refdef.view.forward and friends in reflected scenes
3737 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3740 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3741 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3742 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3743 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3744 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3745 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3746 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3747 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3748 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3749 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3750 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3751 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3755 zNear = r_refdef.nearclip;
3756 nudge = 1.0 - 1.0 / (1<<23);
3757 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3758 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3759 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3760 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3761 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3762 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3763 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3764 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3770 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3771 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3772 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3773 r_refdef.view.frustum[0].dist = m[15] - m[12];
3775 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3776 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3777 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3778 r_refdef.view.frustum[1].dist = m[15] + m[12];
3780 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3781 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3782 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3783 r_refdef.view.frustum[2].dist = m[15] - m[13];
3785 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3786 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3787 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3788 r_refdef.view.frustum[3].dist = m[15] + m[13];
3790 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3791 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3792 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3793 r_refdef.view.frustum[4].dist = m[15] - m[14];
3795 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3796 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3797 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3798 r_refdef.view.frustum[5].dist = m[15] + m[14];
3801 if (r_refdef.view.useperspective)
3803 slopex = 1.0 / r_refdef.view.frustum_x;
3804 slopey = 1.0 / r_refdef.view.frustum_y;
3805 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3806 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3807 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3808 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3809 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3811 // Leaving those out was a mistake, those were in the old code, and they
3812 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3813 // I couldn't reproduce it after adding those normalizations. --blub
3814 VectorNormalize(r_refdef.view.frustum[0].normal);
3815 VectorNormalize(r_refdef.view.frustum[1].normal);
3816 VectorNormalize(r_refdef.view.frustum[2].normal);
3817 VectorNormalize(r_refdef.view.frustum[3].normal);
3819 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3820 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]);
3821 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]);
3822 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]);
3823 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]);
3825 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3826 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3827 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3828 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3829 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3833 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3834 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3835 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3836 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3837 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3838 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3839 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3840 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3841 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3842 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3844 r_refdef.view.numfrustumplanes = 5;
3846 if (r_refdef.view.useclipplane)
3848 r_refdef.view.numfrustumplanes = 6;
3849 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3852 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3853 PlaneClassify(r_refdef.view.frustum + i);
3855 // LordHavoc: note to all quake engine coders, Quake had a special case
3856 // for 90 degrees which assumed a square view (wrong), so I removed it,
3857 // Quake2 has it disabled as well.
3859 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3860 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3861 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3862 //PlaneClassify(&frustum[0]);
3864 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3865 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3866 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3867 //PlaneClassify(&frustum[1]);
3869 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3870 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3871 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3872 //PlaneClassify(&frustum[2]);
3874 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3875 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3876 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3877 //PlaneClassify(&frustum[3]);
3880 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3881 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3882 //PlaneClassify(&frustum[4]);
3885 void R_View_Update(void)
3887 R_View_SetFrustum();
3888 R_View_WorldVisibility(r_refdef.view.useclipplane);
3889 R_View_UpdateEntityVisible();
3890 R_View_UpdateEntityLighting();
3893 void R_SetupView(qboolean allowwaterclippingplane)
3895 const double *customclipplane = NULL;
3897 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3899 // LordHavoc: couldn't figure out how to make this approach the
3900 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3901 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3902 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3903 dist = r_refdef.view.clipplane.dist;
3904 plane[0] = r_refdef.view.clipplane.normal[0];
3905 plane[1] = r_refdef.view.clipplane.normal[1];
3906 plane[2] = r_refdef.view.clipplane.normal[2];
3908 customclipplane = plane;
3911 if (!r_refdef.view.useperspective)
3912 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);
3913 else if (gl_stencil && r_useinfinitefarclip.integer)
3914 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);
3916 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);
3917 R_SetViewport(&r_refdef.view.viewport);
3920 void R_ResetViewRendering2D(void)
3922 r_viewport_t viewport;
3925 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3926 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);
3927 R_SetViewport(&viewport);
3928 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3929 GL_Color(1, 1, 1, 1);
3930 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3931 GL_BlendFunc(GL_ONE, GL_ZERO);
3932 GL_AlphaTest(false);
3933 GL_ScissorTest(false);
3934 GL_DepthMask(false);
3935 GL_DepthRange(0, 1);
3936 GL_DepthTest(false);
3937 R_Mesh_Matrix(&identitymatrix);
3938 R_Mesh_ResetTextureState();
3939 GL_PolygonOffset(0, 0);
3940 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3941 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3942 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3943 qglStencilMask(~0);CHECKGLERROR
3944 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3945 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3946 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3947 R_SetupGenericShader(true);
3950 void R_ResetViewRendering3D(void)
3955 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3956 GL_Color(1, 1, 1, 1);
3957 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3958 GL_BlendFunc(GL_ONE, GL_ZERO);
3959 GL_AlphaTest(false);
3960 GL_ScissorTest(true);
3962 GL_DepthRange(0, 1);
3964 R_Mesh_Matrix(&identitymatrix);
3965 R_Mesh_ResetTextureState();
3966 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3967 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3968 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3969 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3970 qglStencilMask(~0);CHECKGLERROR
3971 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3972 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3973 GL_CullFace(r_refdef.view.cullface_back);
3974 R_SetupGenericShader(true);
3977 void R_RenderScene(void);
3978 void R_RenderWaterPlanes(void);
3980 static void R_Water_StartFrame(void)
3983 int waterwidth, waterheight, texturewidth, textureheight;
3984 r_waterstate_waterplane_t *p;
3986 // set waterwidth and waterheight to the water resolution that will be
3987 // used (often less than the screen resolution for faster rendering)
3988 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3989 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3991 // calculate desired texture sizes
3992 // can't use water if the card does not support the texture size
3993 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3994 texturewidth = textureheight = waterwidth = waterheight = 0;
3995 else if (gl_support_arb_texture_non_power_of_two)
3997 texturewidth = waterwidth;
3998 textureheight = waterheight;
4002 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4003 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4006 // allocate textures as needed
4007 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4009 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4010 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4012 if (p->texture_refraction)
4013 R_FreeTexture(p->texture_refraction);
4014 p->texture_refraction = NULL;
4015 if (p->texture_reflection)
4016 R_FreeTexture(p->texture_reflection);
4017 p->texture_reflection = NULL;
4019 memset(&r_waterstate, 0, sizeof(r_waterstate));
4020 r_waterstate.texturewidth = texturewidth;
4021 r_waterstate.textureheight = textureheight;
4024 if (r_waterstate.texturewidth)
4026 r_waterstate.enabled = true;
4028 // when doing a reduced render (HDR) we want to use a smaller area
4029 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4030 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4032 // set up variables that will be used in shader setup
4033 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4034 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4035 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4036 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4039 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4040 r_waterstate.numwaterplanes = 0;
4043 void R_Water_AddWaterPlane(msurface_t *surface)
4045 int triangleindex, planeindex;
4051 r_waterstate_waterplane_t *p;
4052 texture_t *t = R_GetCurrentTexture(surface->texture);
4053 // just use the first triangle with a valid normal for any decisions
4054 VectorClear(normal);
4055 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4057 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4058 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4059 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4060 TriangleNormal(vert[0], vert[1], vert[2], normal);
4061 if (VectorLength2(normal) >= 0.001)
4065 VectorCopy(normal, plane.normal);
4066 VectorNormalize(plane.normal);
4067 plane.dist = DotProduct(vert[0], plane.normal);
4068 PlaneClassify(&plane);
4069 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4071 // skip backfaces (except if nocullface is set)
4072 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4074 VectorNegate(plane.normal, plane.normal);
4076 PlaneClassify(&plane);
4080 // find a matching plane if there is one
4081 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4082 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4084 if (planeindex >= r_waterstate.maxwaterplanes)
4085 return; // nothing we can do, out of planes
4087 // if this triangle does not fit any known plane rendered this frame, add one
4088 if (planeindex >= r_waterstate.numwaterplanes)
4090 // store the new plane
4091 r_waterstate.numwaterplanes++;
4093 // clear materialflags and pvs
4094 p->materialflags = 0;
4095 p->pvsvalid = false;
4097 // merge this surface's materialflags into the waterplane
4098 p->materialflags |= t->currentmaterialflags;
4099 // merge this surface's PVS into the waterplane
4100 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4101 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4102 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4104 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4109 static void R_Water_ProcessPlanes(void)
4111 r_refdef_view_t originalview;
4112 r_refdef_view_t myview;
4114 r_waterstate_waterplane_t *p;
4116 originalview = r_refdef.view;
4118 // make sure enough textures are allocated
4119 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4121 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4123 if (!p->texture_refraction)
4124 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);
4125 if (!p->texture_refraction)
4129 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4131 if (!p->texture_reflection)
4132 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);
4133 if (!p->texture_reflection)
4139 r_refdef.view = originalview;
4140 r_refdef.view.showdebug = false;
4141 r_refdef.view.width = r_waterstate.waterwidth;
4142 r_refdef.view.height = r_waterstate.waterheight;
4143 r_refdef.view.useclipplane = true;
4144 myview = r_refdef.view;
4145 r_waterstate.renderingscene = true;
4146 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4148 // render the normal view scene and copy into texture
4149 // (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)
4150 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4152 r_refdef.view = myview;
4153 r_refdef.view.clipplane = p->plane;
4154 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4155 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4156 PlaneClassify(&r_refdef.view.clipplane);
4158 R_ResetViewRendering3D();
4159 R_ClearScreen(r_refdef.fogenabled);
4163 // copy view into the screen texture
4164 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4165 GL_ActiveTexture(0);
4167 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
4170 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4172 r_refdef.view = myview;
4173 // render reflected scene and copy into texture
4174 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4175 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4176 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4177 r_refdef.view.clipplane = p->plane;
4178 // reverse the cullface settings for this render
4179 r_refdef.view.cullface_front = GL_FRONT;
4180 r_refdef.view.cullface_back = GL_BACK;
4181 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4183 r_refdef.view.usecustompvs = true;
4185 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4187 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4190 R_ResetViewRendering3D();
4191 R_ClearScreen(r_refdef.fogenabled);
4195 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4196 GL_ActiveTexture(0);
4198 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
4201 r_waterstate.renderingscene = false;
4202 r_refdef.view = originalview;
4203 R_ResetViewRendering3D();
4204 R_ClearScreen(r_refdef.fogenabled);
4208 r_refdef.view = originalview;
4209 r_waterstate.renderingscene = false;
4210 Cvar_SetValueQuick(&r_water, 0);
4211 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4215 void R_Bloom_StartFrame(void)
4217 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4219 // set bloomwidth and bloomheight to the bloom resolution that will be
4220 // used (often less than the screen resolution for faster rendering)
4221 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4222 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4223 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4224 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
4225 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
4227 // calculate desired texture sizes
4228 if (gl_support_arb_texture_non_power_of_two)
4230 screentexturewidth = r_refdef.view.width;
4231 screentextureheight = r_refdef.view.height;
4232 bloomtexturewidth = r_bloomstate.bloomwidth;
4233 bloomtextureheight = r_bloomstate.bloomheight;
4237 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4238 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4239 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4240 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4243 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))
4245 Cvar_SetValueQuick(&r_hdr, 0);
4246 Cvar_SetValueQuick(&r_bloom, 0);
4247 Cvar_SetValueQuick(&r_motionblur, 0);
4248 Cvar_SetValueQuick(&r_damageblur, 0);
4251 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)))
4252 screentexturewidth = screentextureheight = 0;
4253 if (!r_hdr.integer && !r_bloom.integer)
4254 bloomtexturewidth = bloomtextureheight = 0;
4256 // allocate textures as needed
4257 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4259 if (r_bloomstate.texture_screen)
4260 R_FreeTexture(r_bloomstate.texture_screen);
4261 r_bloomstate.texture_screen = NULL;
4262 r_bloomstate.screentexturewidth = screentexturewidth;
4263 r_bloomstate.screentextureheight = screentextureheight;
4264 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4265 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);
4267 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4269 if (r_bloomstate.texture_bloom)
4270 R_FreeTexture(r_bloomstate.texture_bloom);
4271 r_bloomstate.texture_bloom = NULL;
4272 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4273 r_bloomstate.bloomtextureheight = bloomtextureheight;
4274 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4275 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);
4278 // when doing a reduced render (HDR) we want to use a smaller area
4279 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4280 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4281 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4282 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4283 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4285 // set up a texcoord array for the full resolution screen image
4286 // (we have to keep this around to copy back during final render)
4287 r_bloomstate.screentexcoord2f[0] = 0;
4288 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4289 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4290 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4291 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4292 r_bloomstate.screentexcoord2f[5] = 0;
4293 r_bloomstate.screentexcoord2f[6] = 0;
4294 r_bloomstate.screentexcoord2f[7] = 0;
4296 // set up a texcoord array for the reduced resolution bloom image
4297 // (which will be additive blended over the screen image)
4298 r_bloomstate.bloomtexcoord2f[0] = 0;
4299 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4300 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4301 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4302 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4303 r_bloomstate.bloomtexcoord2f[5] = 0;
4304 r_bloomstate.bloomtexcoord2f[6] = 0;
4305 r_bloomstate.bloomtexcoord2f[7] = 0;
4307 if (r_hdr.integer || r_bloom.integer)
4309 r_bloomstate.enabled = true;
4310 r_bloomstate.hdr = r_hdr.integer != 0;
4313 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);
4316 void R_Bloom_CopyBloomTexture(float colorscale)
4318 r_refdef.stats.bloom++;
4320 // scale down screen texture to the bloom texture size
4322 R_SetViewport(&r_bloomstate.viewport);
4323 GL_BlendFunc(GL_ONE, GL_ZERO);
4324 GL_Color(colorscale, colorscale, colorscale, 1);
4325 // TODO: optimize with multitexture or GLSL
4326 R_SetupGenericShader(true);
4327 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4328 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4329 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4330 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4332 // we now have a bloom image in the framebuffer
4333 // copy it into the bloom image texture for later processing
4334 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4335 GL_ActiveTexture(0);
4337 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4338 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4341 void R_Bloom_CopyHDRTexture(void)
4343 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4344 GL_ActiveTexture(0);
4346 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
4347 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4350 void R_Bloom_MakeTexture(void)
4353 float xoffset, yoffset, r, brighten;
4355 r_refdef.stats.bloom++;
4357 R_ResetViewRendering2D();
4358 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4359 R_Mesh_ColorPointer(NULL, 0, 0);
4360 R_SetupGenericShader(true);
4362 // we have a bloom image in the framebuffer
4364 R_SetViewport(&r_bloomstate.viewport);
4366 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4369 r = bound(0, r_bloom_colorexponent.value / x, 1);
4370 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4371 GL_Color(r, r, r, 1);
4372 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4373 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4374 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4375 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4377 // copy the vertically blurred bloom view to a texture
4378 GL_ActiveTexture(0);
4380 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4381 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4384 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4385 brighten = r_bloom_brighten.value;
4387 brighten *= r_hdr_range.value;
4388 brighten = sqrt(brighten);
4390 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4391 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4392 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4394 for (dir = 0;dir < 2;dir++)
4396 // blend on at multiple vertical offsets to achieve a vertical blur
4397 // TODO: do offset blends using GLSL
4398 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4399 GL_BlendFunc(GL_ONE, GL_ZERO);
4400 for (x = -range;x <= range;x++)
4402 if (!dir){xoffset = 0;yoffset = x;}
4403 else {xoffset = x;yoffset = 0;}
4404 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4405 yoffset /= (float)r_bloomstate.bloomtextureheight;
4406 // compute a texcoord array with the specified x and y offset
4407 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4408 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4409 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4410 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4411 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4412 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4413 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4414 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4415 // this r value looks like a 'dot' particle, fading sharply to
4416 // black at the edges
4417 // (probably not realistic but looks good enough)
4418 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4419 //r = brighten/(range*2+1);
4420 r = brighten / (range * 2 + 1);
4422 r *= (1 - x*x/(float)(range*range));
4423 GL_Color(r, r, r, 1);
4424 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4425 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4426 GL_BlendFunc(GL_ONE, GL_ONE);
4429 // copy the vertically blurred bloom view to a texture
4430 GL_ActiveTexture(0);
4432 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4433 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4436 // apply subtract last
4437 // (just like it would be in a GLSL shader)
4438 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4440 GL_BlendFunc(GL_ONE, GL_ZERO);
4441 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4442 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4443 GL_Color(1, 1, 1, 1);
4444 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4445 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4447 GL_BlendFunc(GL_ONE, GL_ONE);
4448 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4449 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4450 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4451 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4452 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4453 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4454 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4456 // copy the darkened bloom view to a texture
4457 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4458 GL_ActiveTexture(0);
4460 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4461 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4465 void R_HDR_RenderBloomTexture(void)
4467 int oldwidth, oldheight;
4468 float oldcolorscale;
4470 oldcolorscale = r_refdef.view.colorscale;
4471 oldwidth = r_refdef.view.width;
4472 oldheight = r_refdef.view.height;
4473 r_refdef.view.width = r_bloomstate.bloomwidth;
4474 r_refdef.view.height = r_bloomstate.bloomheight;
4476 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4477 // TODO: add exposure compensation features
4478 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4480 r_refdef.view.showdebug = false;
4481 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4483 R_ResetViewRendering3D();
4485 R_ClearScreen(r_refdef.fogenabled);
4486 if (r_timereport_active)
4487 R_TimeReport("HDRclear");
4490 if (r_timereport_active)
4491 R_TimeReport("visibility");
4493 // only do secondary renders with HDR if r_hdr is 2 or higher
4494 r_waterstate.numwaterplanes = 0;
4495 if (r_waterstate.enabled && r_hdr.integer >= 2)
4496 R_RenderWaterPlanes();
4498 r_refdef.view.showdebug = true;
4500 r_waterstate.numwaterplanes = 0;
4502 R_ResetViewRendering2D();
4504 R_Bloom_CopyHDRTexture();
4505 R_Bloom_MakeTexture();
4507 // restore the view settings
4508 r_refdef.view.width = oldwidth;
4509 r_refdef.view.height = oldheight;
4510 r_refdef.view.colorscale = oldcolorscale;
4512 R_ResetViewRendering3D();
4514 R_ClearScreen(r_refdef.fogenabled);
4515 if (r_timereport_active)
4516 R_TimeReport("viewclear");
4519 static void R_BlendView(void)
4521 if (r_bloomstate.texture_screen)
4523 // make sure the buffer is available
4524 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4526 R_ResetViewRendering2D();
4527 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4528 R_Mesh_ColorPointer(NULL, 0, 0);
4529 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4530 GL_ActiveTexture(0);CHECKGLERROR
4532 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4534 // declare variables
4536 static float avgspeed;
4538 speed = VectorLength(cl.movement_velocity);
4540 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4541 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4543 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4544 speed = bound(0, speed, 1);
4545 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4547 // calculate values into a standard alpha
4548 cl.motionbluralpha = 1 - exp(-
4550 (r_motionblur.value * speed / 80)
4552 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4555 max(0.0001, cl.time - cl.oldtime) // fps independent
4558 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4559 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4561 if (cl.motionbluralpha > 0)
4563 R_SetupGenericShader(true);
4564 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4565 GL_Color(1, 1, 1, cl.motionbluralpha);
4566 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4567 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4568 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4569 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4573 // copy view into the screen texture
4574 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
4575 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4578 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4580 unsigned int permutation =
4581 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4582 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4583 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4584 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4585 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4587 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4589 // render simple bloom effect
4590 // copy the screen and shrink it and darken it for the bloom process
4591 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4592 // make the bloom texture
4593 R_Bloom_MakeTexture();
4596 R_ResetViewRendering2D();
4597 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4598 R_Mesh_ColorPointer(NULL, 0, 0);
4599 GL_Color(1, 1, 1, 1);
4600 GL_BlendFunc(GL_ONE, GL_ZERO);
4601 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4602 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4603 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4604 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4605 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4606 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4607 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4608 if (r_glsl_permutation->loc_TintColor >= 0)
4609 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4610 if (r_glsl_permutation->loc_ClientTime >= 0)
4611 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4612 if (r_glsl_permutation->loc_PixelSize >= 0)
4613 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4614 if (r_glsl_permutation->loc_UserVec1 >= 0)
4616 float a=0, b=0, c=0, d=0;
4617 #if _MSC_VER >= 1400
4618 #define sscanf sscanf_s
4620 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4621 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4623 if (r_glsl_permutation->loc_UserVec2 >= 0)
4625 float a=0, b=0, c=0, d=0;
4626 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4627 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4629 if (r_glsl_permutation->loc_UserVec3 >= 0)
4631 float a=0, b=0, c=0, d=0;
4632 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4633 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4635 if (r_glsl_permutation->loc_UserVec4 >= 0)
4637 float a=0, b=0, c=0, d=0;
4638 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4639 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4641 if (r_glsl_permutation->loc_Saturation >= 0)
4642 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4643 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4644 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4650 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4652 // render high dynamic range bloom effect
4653 // the bloom texture was made earlier this render, so we just need to
4654 // blend it onto the screen...
4655 R_ResetViewRendering2D();
4656 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4657 R_Mesh_ColorPointer(NULL, 0, 0);
4658 R_SetupGenericShader(true);
4659 GL_Color(1, 1, 1, 1);
4660 GL_BlendFunc(GL_ONE, GL_ONE);
4661 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4662 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4663 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4664 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4666 else if (r_bloomstate.texture_bloom)
4668 // render simple bloom effect
4669 // copy the screen and shrink it and darken it for the bloom process
4670 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4671 // make the bloom texture
4672 R_Bloom_MakeTexture();
4673 // put the original screen image back in place and blend the bloom
4675 R_ResetViewRendering2D();
4676 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4677 R_Mesh_ColorPointer(NULL, 0, 0);
4678 GL_Color(1, 1, 1, 1);
4679 GL_BlendFunc(GL_ONE, GL_ZERO);
4680 // do both in one pass if possible
4681 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4682 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4683 if (r_textureunits.integer >= 2 && gl_combine.integer)
4685 R_SetupGenericTwoTextureShader(GL_ADD);
4686 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4687 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4691 R_SetupGenericShader(true);
4692 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4693 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4694 // now blend on the bloom texture
4695 GL_BlendFunc(GL_ONE, GL_ONE);
4696 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4697 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4699 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4700 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4702 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4704 // apply a color tint to the whole view
4705 R_ResetViewRendering2D();
4706 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4707 R_Mesh_ColorPointer(NULL, 0, 0);
4708 R_SetupGenericShader(false);
4709 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4710 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4711 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4715 matrix4x4_t r_waterscrollmatrix;
4717 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4719 if (r_refdef.fog_density)
4721 r_refdef.fogcolor[0] = r_refdef.fog_red;
4722 r_refdef.fogcolor[1] = r_refdef.fog_green;
4723 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4725 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4726 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4727 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4728 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4732 VectorCopy(r_refdef.fogcolor, fogvec);
4733 // color.rgb *= ContrastBoost * SceneBrightness;
4734 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4735 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4736 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4737 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4742 void R_UpdateVariables(void)
4746 r_refdef.scene.ambient = r_ambient.value;
4748 r_refdef.farclip = r_farclip_base.value;
4749 if (r_refdef.scene.worldmodel)
4750 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
4751 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4753 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4754 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4755 r_refdef.polygonfactor = 0;
4756 r_refdef.polygonoffset = 0;
4757 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4758 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4760 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4761 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4762 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4763 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4764 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4765 if (r_showsurfaces.integer)
4767 r_refdef.scene.rtworld = false;
4768 r_refdef.scene.rtworldshadows = false;
4769 r_refdef.scene.rtdlight = false;
4770 r_refdef.scene.rtdlightshadows = false;
4771 r_refdef.lightmapintensity = 0;
4774 if (gamemode == GAME_NEHAHRA)
4776 if (gl_fogenable.integer)
4778 r_refdef.oldgl_fogenable = true;
4779 r_refdef.fog_density = gl_fogdensity.value;
4780 r_refdef.fog_red = gl_fogred.value;
4781 r_refdef.fog_green = gl_foggreen.value;
4782 r_refdef.fog_blue = gl_fogblue.value;
4783 r_refdef.fog_alpha = 1;
4784 r_refdef.fog_start = 0;
4785 r_refdef.fog_end = gl_skyclip.value;
4786 r_refdef.fog_height = 1<<30;
4787 r_refdef.fog_fadedepth = 128;
4789 else if (r_refdef.oldgl_fogenable)
4791 r_refdef.oldgl_fogenable = false;
4792 r_refdef.fog_density = 0;
4793 r_refdef.fog_red = 0;
4794 r_refdef.fog_green = 0;
4795 r_refdef.fog_blue = 0;
4796 r_refdef.fog_alpha = 0;
4797 r_refdef.fog_start = 0;
4798 r_refdef.fog_end = 0;
4799 r_refdef.fog_height = 1<<30;
4800 r_refdef.fog_fadedepth = 128;
4804 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4805 r_refdef.fog_start = max(0, r_refdef.fog_start);
4806 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4808 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4810 if (r_refdef.fog_density && r_drawfog.integer)
4812 r_refdef.fogenabled = true;
4813 // this is the point where the fog reaches 0.9986 alpha, which we
4814 // consider a good enough cutoff point for the texture
4815 // (0.9986 * 256 == 255.6)
4816 if (r_fog_exp2.integer)
4817 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4819 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4820 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4821 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4822 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4823 // fog color was already set
4824 // update the fog texture
4825 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)
4826 R_BuildFogTexture();
4829 r_refdef.fogenabled = false;
4831 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4833 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4835 // build GLSL gamma texture
4836 #define RAMPWIDTH 256
4837 unsigned short ramp[RAMPWIDTH * 3];
4838 unsigned char rampbgr[RAMPWIDTH][4];
4841 r_texture_gammaramps_serial = vid_gammatables_serial;
4843 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4844 for(i = 0; i < RAMPWIDTH; ++i)
4846 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4847 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4848 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4851 if (r_texture_gammaramps)
4853 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4857 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);
4863 // remove GLSL gamma texture
4867 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4868 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4874 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4875 if( scenetype != r_currentscenetype ) {
4876 // store the old scenetype
4877 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4878 r_currentscenetype = scenetype;
4879 // move in the new scene
4880 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4889 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4891 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4892 if( scenetype == r_currentscenetype ) {
4893 return &r_refdef.scene;
4895 return &r_scenes_store[ scenetype ];
4904 void R_RenderView(void)
4906 if (r_timereport_active)
4907 R_TimeReport("start");
4908 r_frame++; // used only by R_GetCurrentTexture
4909 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4911 R_AnimCache_NewFrame();
4913 if (r_refdef.view.isoverlay)
4915 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4916 GL_Clear( GL_DEPTH_BUFFER_BIT );
4917 R_TimeReport("depthclear");
4919 r_refdef.view.showdebug = false;
4921 r_waterstate.enabled = false;
4922 r_waterstate.numwaterplanes = 0;
4930 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4931 return; //Host_Error ("R_RenderView: NULL worldmodel");
4933 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4935 // break apart the view matrix into vectors for various purposes
4936 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4937 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4938 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4939 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4940 // make an inverted copy of the view matrix for tracking sprites
4941 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4943 R_Shadow_UpdateWorldLightSelection();
4945 R_Bloom_StartFrame();
4946 R_Water_StartFrame();
4949 if (r_timereport_active)
4950 R_TimeReport("viewsetup");
4952 R_ResetViewRendering3D();
4954 if (r_refdef.view.clear || r_refdef.fogenabled)
4956 R_ClearScreen(r_refdef.fogenabled);
4957 if (r_timereport_active)
4958 R_TimeReport("viewclear");
4960 r_refdef.view.clear = true;
4962 // this produces a bloom texture to be used in R_BlendView() later
4964 R_HDR_RenderBloomTexture();
4966 r_refdef.view.showdebug = true;
4969 if (r_timereport_active)
4970 R_TimeReport("visibility");
4972 r_waterstate.numwaterplanes = 0;
4973 if (r_waterstate.enabled)
4974 R_RenderWaterPlanes();
4977 r_waterstate.numwaterplanes = 0;
4980 if (r_timereport_active)
4981 R_TimeReport("blendview");
4983 GL_Scissor(0, 0, vid.width, vid.height);
4984 GL_ScissorTest(false);
4988 void R_RenderWaterPlanes(void)
4990 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4992 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4993 if (r_timereport_active)
4994 R_TimeReport("waterworld");
4997 // don't let sound skip if going slow
4998 if (r_refdef.scene.extraupdate)
5001 R_DrawModelsAddWaterPlanes();
5002 if (r_timereport_active)
5003 R_TimeReport("watermodels");
5005 if (r_waterstate.numwaterplanes)
5007 R_Water_ProcessPlanes();
5008 if (r_timereport_active)
5009 R_TimeReport("waterscenes");
5013 extern void R_DrawLightningBeams (void);
5014 extern void VM_CL_AddPolygonsToMeshQueue (void);
5015 extern void R_DrawPortals (void);
5016 extern cvar_t cl_locs_show;
5017 static void R_DrawLocs(void);
5018 static void R_DrawEntityBBoxes(void);
5019 extern cvar_t cl_decals_newsystem;
5020 void R_RenderScene(void)
5022 r_refdef.stats.renders++;
5024 R_Main_ResizeViewCache();
5028 // don't let sound skip if going slow
5029 if (r_refdef.scene.extraupdate)
5032 R_MeshQueue_BeginScene();
5036 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);
5038 if (cl.csqc_vidvars.drawworld)
5040 // don't let sound skip if going slow
5041 if (r_refdef.scene.extraupdate)
5044 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5046 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5047 if (r_timereport_active)
5048 R_TimeReport("worldsky");
5051 if (R_DrawBrushModelsSky() && r_timereport_active)
5052 R_TimeReport("bmodelsky");
5054 if (skyrendermasked && skyrenderlater)
5056 // we have to force off the water clipping plane while rendering sky
5063 R_AnimCache_CacheVisibleEntities();
5065 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5067 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5068 if (r_timereport_active)
5069 R_TimeReport("worlddepth");
5071 if (r_depthfirst.integer >= 2)
5073 R_DrawModelsDepth();
5074 if (r_timereport_active)
5075 R_TimeReport("modeldepth");
5078 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5080 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5081 if (r_timereport_active)
5082 R_TimeReport("world");
5085 // don't let sound skip if going slow
5086 if (r_refdef.scene.extraupdate)
5090 if (r_timereport_active)
5091 R_TimeReport("models");
5093 // don't let sound skip if going slow
5094 if (r_refdef.scene.extraupdate)
5097 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5099 R_DrawModelShadows();
5100 R_ResetViewRendering3D();
5101 // don't let sound skip if going slow
5102 if (r_refdef.scene.extraupdate)
5106 R_ShadowVolumeLighting(false);
5107 if (r_timereport_active)
5108 R_TimeReport("rtlights");
5110 // don't let sound skip if going slow
5111 if (r_refdef.scene.extraupdate)
5114 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5116 R_DrawModelShadows();
5117 R_ResetViewRendering3D();
5118 // don't let sound skip if going slow
5119 if (r_refdef.scene.extraupdate)
5123 if (cl.csqc_vidvars.drawworld)
5125 if (cl_decals_newsystem.integer)
5127 R_DrawModelDecals();
5128 if (r_timereport_active)
5129 R_TimeReport("modeldecals");
5134 if (r_timereport_active)
5135 R_TimeReport("decals");
5139 if (r_timereport_active)
5140 R_TimeReport("particles");
5143 if (r_timereport_active)
5144 R_TimeReport("explosions");
5146 R_DrawLightningBeams();
5147 if (r_timereport_active)
5148 R_TimeReport("lightning");
5151 R_SetupGenericShader(true);
5152 VM_CL_AddPolygonsToMeshQueue();
5154 if (r_refdef.view.showdebug)
5156 if (cl_locs_show.integer)
5159 if (r_timereport_active)
5160 R_TimeReport("showlocs");
5163 if (r_drawportals.integer)
5166 if (r_timereport_active)
5167 R_TimeReport("portals");
5170 if (r_showbboxes.value > 0)
5172 R_DrawEntityBBoxes();
5173 if (r_timereport_active)
5174 R_TimeReport("bboxes");
5178 R_SetupGenericShader(true);
5179 R_MeshQueue_RenderTransparent();
5180 if (r_timereport_active)
5181 R_TimeReport("drawtrans");
5183 R_SetupGenericShader(true);
5185 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))
5187 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5188 if (r_timereport_active)
5189 R_TimeReport("worlddebug");
5190 R_DrawModelsDebug();
5191 if (r_timereport_active)
5192 R_TimeReport("modeldebug");
5195 R_SetupGenericShader(true);
5197 if (cl.csqc_vidvars.drawworld)
5200 if (r_timereport_active)
5201 R_TimeReport("coronas");
5204 // don't let sound skip if going slow
5205 if (r_refdef.scene.extraupdate)
5208 R_ResetViewRendering2D();
5211 static const unsigned short bboxelements[36] =
5221 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5224 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5226 RSurf_ActiveWorldEntity();
5228 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5229 GL_DepthMask(false);
5230 GL_DepthRange(0, 1);
5231 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5232 R_Mesh_ResetTextureState();
5234 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5235 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5236 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5237 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5238 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5239 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5240 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5241 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5242 R_FillColors(color4f, 8, cr, cg, cb, ca);
5243 if (r_refdef.fogenabled)
5245 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5247 f1 = RSurf_FogVertex(v);
5249 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5250 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5251 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5254 R_Mesh_VertexPointer(vertex3f, 0, 0);
5255 R_Mesh_ColorPointer(color4f, 0, 0);
5256 R_Mesh_ResetTextureState();
5257 R_SetupGenericShader(false);
5258 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5261 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5265 prvm_edict_t *edict;
5266 prvm_prog_t *prog_save = prog;
5268 // this function draws bounding boxes of server entities
5272 GL_CullFace(GL_NONE);
5273 R_SetupGenericShader(false);
5277 for (i = 0;i < numsurfaces;i++)
5279 edict = PRVM_EDICT_NUM(surfacelist[i]);
5280 switch ((int)edict->fields.server->solid)
5282 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5283 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5284 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5285 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5286 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5287 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5289 color[3] *= r_showbboxes.value;
5290 color[3] = bound(0, color[3], 1);
5291 GL_DepthTest(!r_showdisabledepthtest.integer);
5292 GL_CullFace(r_refdef.view.cullface_front);
5293 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5299 static void R_DrawEntityBBoxes(void)
5302 prvm_edict_t *edict;
5304 prvm_prog_t *prog_save = prog;
5306 // this function draws bounding boxes of server entities
5312 for (i = 0;i < prog->num_edicts;i++)
5314 edict = PRVM_EDICT_NUM(i);
5315 if (edict->priv.server->free)
5317 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5318 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5320 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5322 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5323 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5329 static const int nomodelelement3i[24] =
5341 static const unsigned short nomodelelement3s[24] =
5353 static const float nomodelvertex3f[6*3] =
5363 static const float nomodelcolor4f[6*4] =
5365 0.0f, 0.0f, 0.5f, 1.0f,
5366 0.0f, 0.0f, 0.5f, 1.0f,
5367 0.0f, 0.5f, 0.0f, 1.0f,
5368 0.0f, 0.5f, 0.0f, 1.0f,
5369 0.5f, 0.0f, 0.0f, 1.0f,
5370 0.5f, 0.0f, 0.0f, 1.0f
5373 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5379 RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
5381 // this is only called once per entity so numsurfaces is always 1, and
5382 // surfacelist is always {0}, so this code does not handle batches
5384 if (rsurface.ent_flags & RENDER_ADDITIVE)
5386 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5387 GL_DepthMask(false);
5389 else if (rsurface.ent_color[3] < 1)
5391 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5392 GL_DepthMask(false);
5396 GL_BlendFunc(GL_ONE, GL_ZERO);
5399 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5400 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5401 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5402 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5403 R_SetupGenericShader(false);
5404 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5405 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5406 R_Mesh_ColorPointer(color4f, 0, 0);
5407 for (i = 0, c = color4f;i < 6;i++, c += 4)
5409 c[0] *= rsurface.ent_color[0];
5410 c[1] *= rsurface.ent_color[1];
5411 c[2] *= rsurface.ent_color[2];
5412 c[3] *= rsurface.ent_color[3];
5414 if (r_refdef.fogenabled)
5416 for (i = 0, c = color4f;i < 6;i++, c += 4)
5418 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5420 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5421 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5422 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5425 R_Mesh_ResetTextureState();
5426 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5429 void R_DrawNoModel(entity_render_t *ent)
5432 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5433 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5434 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5436 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5439 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5441 vec3_t right1, right2, diff, normal;
5443 VectorSubtract (org2, org1, normal);
5445 // calculate 'right' vector for start
5446 VectorSubtract (r_refdef.view.origin, org1, diff);
5447 CrossProduct (normal, diff, right1);
5448 VectorNormalize (right1);
5450 // calculate 'right' vector for end
5451 VectorSubtract (r_refdef.view.origin, org2, diff);
5452 CrossProduct (normal, diff, right2);
5453 VectorNormalize (right2);
5455 vert[ 0] = org1[0] + width * right1[0];
5456 vert[ 1] = org1[1] + width * right1[1];
5457 vert[ 2] = org1[2] + width * right1[2];
5458 vert[ 3] = org1[0] - width * right1[0];
5459 vert[ 4] = org1[1] - width * right1[1];
5460 vert[ 5] = org1[2] - width * right1[2];
5461 vert[ 6] = org2[0] - width * right2[0];
5462 vert[ 7] = org2[1] - width * right2[1];
5463 vert[ 8] = org2[2] - width * right2[2];
5464 vert[ 9] = org2[0] + width * right2[0];
5465 vert[10] = org2[1] + width * right2[1];
5466 vert[11] = org2[2] + width * right2[2];
5469 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
5471 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5472 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5473 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5474 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5475 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5476 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5477 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5478 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5479 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5480 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5481 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5482 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5485 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5490 VectorSet(v, x, y, z);
5491 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5492 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5494 if (i == mesh->numvertices)
5496 if (mesh->numvertices < mesh->maxvertices)
5498 VectorCopy(v, vertex3f);
5499 mesh->numvertices++;
5501 return mesh->numvertices;
5507 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5511 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5512 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5513 e = mesh->element3i + mesh->numtriangles * 3;
5514 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5516 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5517 if (mesh->numtriangles < mesh->maxtriangles)
5522 mesh->numtriangles++;
5524 element[1] = element[2];
5528 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5532 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5533 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5534 e = mesh->element3i + mesh->numtriangles * 3;
5535 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5537 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5538 if (mesh->numtriangles < mesh->maxtriangles)
5543 mesh->numtriangles++;
5545 element[1] = element[2];
5549 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5550 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5552 int planenum, planenum2;
5555 mplane_t *plane, *plane2;
5557 double temppoints[2][256*3];
5558 // figure out how large a bounding box we need to properly compute this brush
5560 for (w = 0;w < numplanes;w++)
5561 maxdist = max(maxdist, fabs(planes[w].dist));
5562 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5563 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5564 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5568 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5569 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5571 if (planenum2 == planenum)
5573 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);
5576 if (tempnumpoints < 3)
5578 // generate elements forming a triangle fan for this polygon
5579 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5583 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)
5585 texturelayer_t *layer;
5586 layer = t->currentlayers + t->currentnumlayers++;
5588 layer->depthmask = depthmask;
5589 layer->blendfunc1 = blendfunc1;
5590 layer->blendfunc2 = blendfunc2;
5591 layer->texture = texture;
5592 layer->texmatrix = *matrix;
5593 layer->color[0] = r * r_refdef.view.colorscale;
5594 layer->color[1] = g * r_refdef.view.colorscale;
5595 layer->color[2] = b * r_refdef.view.colorscale;
5596 layer->color[3] = a;
5599 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5602 index = parms[2] + r_refdef.scene.time * parms[3];
5603 index -= floor(index);
5607 case Q3WAVEFUNC_NONE:
5608 case Q3WAVEFUNC_NOISE:
5609 case Q3WAVEFUNC_COUNT:
5612 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5613 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5614 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5615 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5616 case Q3WAVEFUNC_TRIANGLE:
5618 f = index - floor(index);
5629 return (float)(parms[0] + parms[1] * f);
5632 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5637 matrix4x4_t matrix, temp;
5638 switch(tcmod->tcmod)
5642 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5643 matrix = r_waterscrollmatrix;
5645 matrix = identitymatrix;
5647 case Q3TCMOD_ENTITYTRANSLATE:
5648 // this is used in Q3 to allow the gamecode to control texcoord
5649 // scrolling on the entity, which is not supported in darkplaces yet.
5650 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5652 case Q3TCMOD_ROTATE:
5653 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5654 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5655 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5658 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5660 case Q3TCMOD_SCROLL:
5661 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5663 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5664 w = (int) tcmod->parms[0];
5665 h = (int) tcmod->parms[1];
5666 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5668 idx = (int) floor(f * w * h);
5669 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5671 case Q3TCMOD_STRETCH:
5672 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5673 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5675 case Q3TCMOD_TRANSFORM:
5676 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5677 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5678 VectorSet(tcmat + 6, 0 , 0 , 1);
5679 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5680 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5682 case Q3TCMOD_TURBULENT:
5683 // this is handled in the RSurf_PrepareVertices function
5684 matrix = identitymatrix;
5688 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5691 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5693 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5694 char name[MAX_QPATH];
5695 skinframe_t *skinframe;
5696 unsigned char pixels[296*194];
5697 strlcpy(cache->name, skinname, sizeof(cache->name));
5698 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5699 if (developer_loading.integer)
5700 Con_Printf("loading %s\n", name);
5701 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5702 if (!skinframe || !skinframe->base)
5705 fs_offset_t filesize;
5707 f = FS_LoadFile(name, tempmempool, true, &filesize);
5710 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5711 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5715 cache->skinframe = skinframe;
5718 texture_t *R_GetCurrentTexture(texture_t *t)
5721 const entity_render_t *ent = rsurface.entity;
5722 dp_model_t *model = ent->model;
5723 q3shaderinfo_layer_tcmod_t *tcmod;
5725 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5726 return t->currentframe;
5727 t->update_lastrenderframe = r_frame;
5728 t->update_lastrenderentity = (void *)ent;
5730 // switch to an alternate material if this is a q1bsp animated material
5732 texture_t *texture = t;
5733 int s = rsurface.ent_skinnum;
5734 if ((unsigned int)s >= (unsigned int)model->numskins)
5736 if (model->skinscenes)
5738 if (model->skinscenes[s].framecount > 1)
5739 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5741 s = model->skinscenes[s].firstframe;
5744 t = t + s * model->num_surfaces;
5747 // use an alternate animation if the entity's frame is not 0,
5748 // and only if the texture has an alternate animation
5749 if (rsurface.ent_alttextures && t->anim_total[1])
5750 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5752 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5754 texture->currentframe = t;
5757 // update currentskinframe to be a qw skin or animation frame
5758 if (rsurface.ent_qwskin >= 0)
5760 i = rsurface.ent_qwskin;
5761 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5763 r_qwskincache_size = cl.maxclients;
5765 Mem_Free(r_qwskincache);
5766 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5768 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5769 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5770 t->currentskinframe = r_qwskincache[i].skinframe;
5771 if (t->currentskinframe == NULL)
5772 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5774 else if (t->numskinframes >= 2)
5775 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5776 if (t->backgroundnumskinframes >= 2)
5777 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5779 t->currentmaterialflags = t->basematerialflags;
5780 t->currentalpha = rsurface.ent_color[3];
5781 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5782 t->currentalpha *= r_wateralpha.value;
5783 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5784 t->currentalpha *= t->r_water_wateralpha;
5785 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5786 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5787 if (!(rsurface.ent_flags & RENDER_LIGHT))
5788 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5789 else if (rsurface.modeltexcoordlightmap2f == NULL)
5791 // pick a model lighting mode
5792 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5793 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5795 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5797 if (rsurface.ent_flags & RENDER_ADDITIVE)
5798 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5799 else if (t->currentalpha < 1)
5800 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5801 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5802 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5803 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5804 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5805 if (t->backgroundnumskinframes)
5806 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5807 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5809 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5810 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5813 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5815 // there is no tcmod
5816 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5818 t->currenttexmatrix = r_waterscrollmatrix;
5819 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5821 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
5823 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5824 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5827 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5828 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5829 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5830 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5832 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5833 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5834 t->glosstexture = r_texture_black;
5835 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5836 t->backgroundglosstexture = r_texture_black;
5837 t->specularpower = r_shadow_glossexponent.value;
5838 // TODO: store reference values for these in the texture?
5839 t->specularscale = 0;
5840 if (r_shadow_gloss.integer > 0)
5842 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5844 if (r_shadow_glossintensity.value > 0)
5846 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5847 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5848 t->specularscale = r_shadow_glossintensity.value;
5851 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5853 t->glosstexture = r_texture_white;
5854 t->backgroundglosstexture = r_texture_white;
5855 t->specularscale = r_shadow_gloss2intensity.value;
5856 t->specularpower = r_shadow_gloss2exponent.value;
5859 t->specularscale *= t->specularscalemod;
5860 t->specularpower *= t->specularpowermod;
5862 // lightmaps mode looks bad with dlights using actual texturing, so turn
5863 // off the colormap and glossmap, but leave the normalmap on as it still
5864 // accurately represents the shading involved
5865 if (gl_lightmaps.integer)
5867 t->basetexture = r_texture_grey128;
5868 t->backgroundbasetexture = NULL;
5869 t->specularscale = 0;
5870 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5873 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5874 VectorClear(t->dlightcolor);
5875 t->currentnumlayers = 0;
5876 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5879 int blendfunc1, blendfunc2;
5881 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5883 blendfunc1 = GL_SRC_ALPHA;
5884 blendfunc2 = GL_ONE;
5886 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5888 blendfunc1 = GL_SRC_ALPHA;
5889 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5891 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5893 blendfunc1 = t->customblendfunc[0];
5894 blendfunc2 = t->customblendfunc[1];
5898 blendfunc1 = GL_ONE;
5899 blendfunc2 = GL_ZERO;
5901 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5902 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5903 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5904 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5906 // fullbright is not affected by r_refdef.lightmapintensity
5907 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]);
5908 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5909 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5910 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5911 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5915 vec3_t ambientcolor;
5917 // set the color tint used for lights affecting this surface
5918 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5920 // q3bsp has no lightmap updates, so the lightstylevalue that
5921 // would normally be baked into the lightmap must be
5922 // applied to the color
5923 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5924 if (model->type == mod_brushq3)
5925 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5926 colorscale *= r_refdef.lightmapintensity;
5927 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5928 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5929 // basic lit geometry
5930 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]);
5931 // add pants/shirt if needed
5932 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5933 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5934 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5935 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5936 // now add ambient passes if needed
5937 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5939 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]);
5940 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5941 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
5942 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5943 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
5946 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5947 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]);
5948 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5950 // if this is opaque use alpha blend which will darken the earlier
5953 // if this is an alpha blended material, all the earlier passes
5954 // were darkened by fog already, so we only need to add the fog
5955 // color ontop through the fog mask texture
5957 // if this is an additive blended material, all the earlier passes
5958 // were darkened by fog already, and we should not add fog color
5959 // (because the background was not darkened, there is no fog color
5960 // that was lost behind it).
5961 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]);
5965 return t->currentframe;
5968 rsurfacestate_t rsurface;
5970 void R_Mesh_ResizeArrays(int newvertices)
5973 if (rsurface.array_size >= newvertices)
5975 if (rsurface.array_modelvertex3f)
5976 Mem_Free(rsurface.array_modelvertex3f);
5977 rsurface.array_size = (newvertices + 1023) & ~1023;
5978 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5979 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5980 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5981 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5982 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5983 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5984 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5985 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5986 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5987 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5988 rsurface.array_color4f = base + rsurface.array_size * 27;
5989 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5992 void RSurf_ActiveWorldEntity(void)
5994 dp_model_t *model = r_refdef.scene.worldmodel;
5995 //if (rsurface.entity == r_refdef.scene.worldentity)
5997 rsurface.entity = r_refdef.scene.worldentity;
5998 rsurface.ent_skinnum = 0;
5999 rsurface.ent_qwskin = -1;
6000 rsurface.ent_shadertime = 0;
6001 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
6002 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6003 if (rsurface.array_size < model->surfmesh.num_vertices)
6004 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6005 rsurface.matrix = identitymatrix;
6006 rsurface.inversematrix = identitymatrix;
6007 rsurface.matrixscale = 1;
6008 rsurface.inversematrixscale = 1;
6009 R_Mesh_Matrix(&identitymatrix);
6010 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6011 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6012 rsurface.fograngerecip = r_refdef.fograngerecip;
6013 rsurface.fogheightfade = r_refdef.fogheightfade;
6014 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6015 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6016 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6017 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6018 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6019 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6020 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6021 VectorSet(rsurface.glowmod, 1, 1, 1);
6022 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6023 rsurface.frameblend[0].lerp = 1;
6024 rsurface.ent_alttextures = false;
6025 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6026 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6027 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6028 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6029 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6030 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6031 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6032 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6033 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6034 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6035 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6036 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6037 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6038 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6039 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6040 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6041 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6042 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6043 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6044 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6045 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6046 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6047 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6048 rsurface.modelelement3i = model->surfmesh.data_element3i;
6049 rsurface.modelelement3s = model->surfmesh.data_element3s;
6050 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6051 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6052 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6053 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6054 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6055 rsurface.modelsurfaces = model->data_surfaces;
6056 rsurface.generatedvertex = false;
6057 rsurface.vertex3f = rsurface.modelvertex3f;
6058 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6059 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6060 rsurface.svector3f = rsurface.modelsvector3f;
6061 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6062 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6063 rsurface.tvector3f = rsurface.modeltvector3f;
6064 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6065 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6066 rsurface.normal3f = rsurface.modelnormal3f;
6067 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6068 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6069 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6072 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6074 dp_model_t *model = ent->model;
6075 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6077 rsurface.entity = (entity_render_t *)ent;
6078 rsurface.ent_skinnum = ent->skinnum;
6079 rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
6080 rsurface.ent_shadertime = ent->shadertime;
6081 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6082 rsurface.ent_flags = ent->flags;
6083 if (rsurface.array_size < model->surfmesh.num_vertices)
6084 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6085 rsurface.matrix = ent->matrix;
6086 rsurface.inversematrix = ent->inversematrix;
6087 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6088 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6089 R_Mesh_Matrix(&rsurface.matrix);
6090 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6091 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6092 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6093 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6094 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6095 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6096 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6097 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6098 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6099 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6100 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6101 VectorCopy(ent->glowmod, rsurface.glowmod);
6102 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6103 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6104 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6105 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6106 if (ent->model->brush.submodel)
6108 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6109 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6111 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6113 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6115 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6116 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6117 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6118 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6120 else if (wanttangents)
6122 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6123 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6124 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6125 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6126 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6128 else if (wantnormals)
6130 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6131 rsurface.modelsvector3f = NULL;
6132 rsurface.modeltvector3f = NULL;
6133 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6134 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6138 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6139 rsurface.modelsvector3f = NULL;
6140 rsurface.modeltvector3f = NULL;
6141 rsurface.modelnormal3f = NULL;
6142 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6144 rsurface.modelvertex3f_bufferobject = 0;
6145 rsurface.modelvertex3f_bufferoffset = 0;
6146 rsurface.modelsvector3f_bufferobject = 0;
6147 rsurface.modelsvector3f_bufferoffset = 0;
6148 rsurface.modeltvector3f_bufferobject = 0;
6149 rsurface.modeltvector3f_bufferoffset = 0;
6150 rsurface.modelnormal3f_bufferobject = 0;
6151 rsurface.modelnormal3f_bufferoffset = 0;
6152 rsurface.generatedvertex = true;
6156 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6157 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6158 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6159 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6160 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6161 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6162 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6163 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6164 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6165 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6166 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6167 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6168 rsurface.generatedvertex = false;
6170 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6171 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6172 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6173 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6174 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6175 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6176 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6177 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6178 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6179 rsurface.modelelement3i = model->surfmesh.data_element3i;
6180 rsurface.modelelement3s = model->surfmesh.data_element3s;
6181 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6182 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6183 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6184 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6185 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6186 rsurface.modelsurfaces = model->data_surfaces;
6187 rsurface.vertex3f = rsurface.modelvertex3f;
6188 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6189 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6190 rsurface.svector3f = rsurface.modelsvector3f;
6191 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6192 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6193 rsurface.tvector3f = rsurface.modeltvector3f;
6194 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6195 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6196 rsurface.normal3f = rsurface.modelnormal3f;
6197 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6198 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6199 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6202 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
6204 rsurface.entity = r_refdef.scene.worldentity;
6205 rsurface.ent_skinnum = 0;
6206 rsurface.ent_qwskin = -1;
6207 rsurface.ent_shadertime = shadertime;
6208 Vector4Set(rsurface.ent_color, r, g, b, a);
6209 rsurface.ent_flags = entflags;
6210 rsurface.modelnum_vertices = numvertices;
6211 rsurface.modelnum_triangles = numtriangles;
6212 if (rsurface.array_size < rsurface.modelnum_vertices)
6213 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6214 rsurface.matrix = *matrix;
6215 rsurface.inversematrix = *inversematrix;
6216 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6217 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6218 R_Mesh_Matrix(&rsurface.matrix);
6219 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6220 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6221 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6222 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6223 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6224 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6225 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6226 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6227 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6228 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6229 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6230 VectorSet(rsurface.glowmod, 1, 1, 1);
6231 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6232 rsurface.frameblend[0].lerp = 1;
6233 rsurface.ent_alttextures = false;
6234 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6235 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6238 rsurface.modelvertex3f = vertex3f;
6239 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6240 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6241 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6243 else if (wantnormals)
6245 rsurface.modelvertex3f = vertex3f;
6246 rsurface.modelsvector3f = NULL;
6247 rsurface.modeltvector3f = NULL;
6248 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6252 rsurface.modelvertex3f = vertex3f;
6253 rsurface.modelsvector3f = NULL;
6254 rsurface.modeltvector3f = NULL;
6255 rsurface.modelnormal3f = NULL;
6257 rsurface.modelvertex3f_bufferobject = 0;
6258 rsurface.modelvertex3f_bufferoffset = 0;
6259 rsurface.modelsvector3f_bufferobject = 0;
6260 rsurface.modelsvector3f_bufferoffset = 0;
6261 rsurface.modeltvector3f_bufferobject = 0;
6262 rsurface.modeltvector3f_bufferoffset = 0;
6263 rsurface.modelnormal3f_bufferobject = 0;
6264 rsurface.modelnormal3f_bufferoffset = 0;
6265 rsurface.generatedvertex = true;
6266 rsurface.modellightmapcolor4f = color4f;
6267 rsurface.modellightmapcolor4f_bufferobject = 0;
6268 rsurface.modellightmapcolor4f_bufferoffset = 0;
6269 rsurface.modeltexcoordtexture2f = texcoord2f;
6270 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6271 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6272 rsurface.modeltexcoordlightmap2f = NULL;
6273 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6274 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6275 rsurface.modelelement3i = element3i;
6276 rsurface.modelelement3s = element3s;
6277 rsurface.modelelement3i_bufferobject = 0;
6278 rsurface.modelelement3s_bufferobject = 0;
6279 rsurface.modellightmapoffsets = NULL;
6280 rsurface.modelsurfaces = NULL;
6281 rsurface.vertex3f = rsurface.modelvertex3f;
6282 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6283 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6284 rsurface.svector3f = rsurface.modelsvector3f;
6285 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6286 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6287 rsurface.tvector3f = rsurface.modeltvector3f;
6288 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6289 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6290 rsurface.normal3f = rsurface.modelnormal3f;
6291 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6292 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6293 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6295 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6297 if ((wantnormals || wanttangents) && !normal3f)
6298 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6299 if (wanttangents && !svector3f)
6300 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);
6304 float RSurf_FogPoint(const float *v)
6306 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6307 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6308 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6309 float FogHeightFade = r_refdef.fogheightfade;
6311 unsigned int fogmasktableindex;
6312 if (r_refdef.fogplaneviewabove)
6313 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6315 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6316 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6317 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6320 float RSurf_FogVertex(const float *v)
6322 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6323 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6324 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6325 float FogHeightFade = rsurface.fogheightfade;
6327 unsigned int fogmasktableindex;
6328 if (r_refdef.fogplaneviewabove)
6329 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6331 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6332 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6333 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6336 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6337 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6340 int texturesurfaceindex;
6345 const float *v1, *in_tc;
6347 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6349 q3shaderinfo_deform_t *deform;
6350 // 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
6351 if (rsurface.generatedvertex)
6353 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6354 generatenormals = true;
6355 for (i = 0;i < Q3MAXDEFORMS;i++)
6357 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6359 generatetangents = true;
6360 generatenormals = true;
6362 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6363 generatenormals = true;
6365 if (generatenormals && !rsurface.modelnormal3f)
6367 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6368 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6369 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6370 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6372 if (generatetangents && !rsurface.modelsvector3f)
6374 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6375 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6376 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6377 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6378 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6379 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6380 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);
6383 rsurface.vertex3f = rsurface.modelvertex3f;
6384 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6385 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6386 rsurface.svector3f = rsurface.modelsvector3f;
6387 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6388 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6389 rsurface.tvector3f = rsurface.modeltvector3f;
6390 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6391 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6392 rsurface.normal3f = rsurface.modelnormal3f;
6393 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6394 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6395 // if vertices are deformed (sprite flares and things in maps, possibly
6396 // water waves, bulges and other deformations), generate them into
6397 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6398 // (may be static model data or generated data for an animated model, or
6399 // the previous deform pass)
6400 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6402 switch (deform->deform)
6405 case Q3DEFORM_PROJECTIONSHADOW:
6406 case Q3DEFORM_TEXT0:
6407 case Q3DEFORM_TEXT1:
6408 case Q3DEFORM_TEXT2:
6409 case Q3DEFORM_TEXT3:
6410 case Q3DEFORM_TEXT4:
6411 case Q3DEFORM_TEXT5:
6412 case Q3DEFORM_TEXT6:
6413 case Q3DEFORM_TEXT7:
6416 case Q3DEFORM_AUTOSPRITE:
6417 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6418 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6419 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6420 VectorNormalize(newforward);
6421 VectorNormalize(newright);
6422 VectorNormalize(newup);
6423 // make deformed versions of only the model vertices used by the specified surfaces
6424 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6426 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6427 // a single autosprite surface can contain multiple sprites...
6428 for (j = 0;j < surface->num_vertices - 3;j += 4)
6430 VectorClear(center);
6431 for (i = 0;i < 4;i++)
6432 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6433 VectorScale(center, 0.25f, center);
6434 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6435 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6436 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6437 for (i = 0;i < 4;i++)
6439 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6440 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6443 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);
6444 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);
6446 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6447 rsurface.vertex3f_bufferobject = 0;
6448 rsurface.vertex3f_bufferoffset = 0;
6449 rsurface.svector3f = rsurface.array_deformedsvector3f;
6450 rsurface.svector3f_bufferobject = 0;
6451 rsurface.svector3f_bufferoffset = 0;
6452 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6453 rsurface.tvector3f_bufferobject = 0;
6454 rsurface.tvector3f_bufferoffset = 0;
6455 rsurface.normal3f = rsurface.array_deformednormal3f;
6456 rsurface.normal3f_bufferobject = 0;
6457 rsurface.normal3f_bufferoffset = 0;
6459 case Q3DEFORM_AUTOSPRITE2:
6460 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6461 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6462 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6463 VectorNormalize(newforward);
6464 VectorNormalize(newright);
6465 VectorNormalize(newup);
6466 // make deformed versions of only the model vertices used by the specified surfaces
6467 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6469 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6470 const float *v1, *v2;
6480 memset(shortest, 0, sizeof(shortest));
6481 // a single autosprite surface can contain multiple sprites...
6482 for (j = 0;j < surface->num_vertices - 3;j += 4)
6484 VectorClear(center);
6485 for (i = 0;i < 4;i++)
6486 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6487 VectorScale(center, 0.25f, center);
6488 // find the two shortest edges, then use them to define the
6489 // axis vectors for rotating around the central axis
6490 for (i = 0;i < 6;i++)
6492 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6493 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6495 Debug_PolygonBegin(NULL, 0);
6496 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6497 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);
6498 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6501 l = VectorDistance2(v1, v2);
6502 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6504 l += (1.0f / 1024.0f);
6505 if (shortest[0].length2 > l || i == 0)
6507 shortest[1] = shortest[0];
6508 shortest[0].length2 = l;
6509 shortest[0].v1 = v1;
6510 shortest[0].v2 = v2;
6512 else if (shortest[1].length2 > l || i == 1)
6514 shortest[1].length2 = l;
6515 shortest[1].v1 = v1;
6516 shortest[1].v2 = v2;
6519 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6520 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6522 Debug_PolygonBegin(NULL, 0);
6523 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6524 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);
6525 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6528 // this calculates the right vector from the shortest edge
6529 // and the up vector from the edge midpoints
6530 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6531 VectorNormalize(right);
6532 VectorSubtract(end, start, up);
6533 VectorNormalize(up);
6534 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6535 VectorSubtract(rsurface.localvieworigin, center, forward);
6536 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6537 VectorNegate(forward, forward);
6538 VectorReflect(forward, 0, up, forward);
6539 VectorNormalize(forward);
6540 CrossProduct(up, forward, newright);
6541 VectorNormalize(newright);
6543 Debug_PolygonBegin(NULL, 0);
6544 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);
6545 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6546 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6550 Debug_PolygonBegin(NULL, 0);
6551 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6552 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6553 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6556 // rotate the quad around the up axis vector, this is made
6557 // especially easy by the fact we know the quad is flat,
6558 // so we only have to subtract the center position and
6559 // measure distance along the right vector, and then
6560 // multiply that by the newright vector and add back the
6562 // we also need to subtract the old position to undo the
6563 // displacement from the center, which we do with a
6564 // DotProduct, the subtraction/addition of center is also
6565 // optimized into DotProducts here
6566 l = DotProduct(right, center);
6567 for (i = 0;i < 4;i++)
6569 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6570 f = DotProduct(right, v1) - l;
6571 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6574 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);
6575 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);
6577 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6578 rsurface.vertex3f_bufferobject = 0;
6579 rsurface.vertex3f_bufferoffset = 0;
6580 rsurface.svector3f = rsurface.array_deformedsvector3f;
6581 rsurface.svector3f_bufferobject = 0;
6582 rsurface.svector3f_bufferoffset = 0;
6583 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6584 rsurface.tvector3f_bufferobject = 0;
6585 rsurface.tvector3f_bufferoffset = 0;
6586 rsurface.normal3f = rsurface.array_deformednormal3f;
6587 rsurface.normal3f_bufferobject = 0;
6588 rsurface.normal3f_bufferoffset = 0;
6590 case Q3DEFORM_NORMAL:
6591 // deform the normals to make reflections wavey
6592 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6594 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6595 for (j = 0;j < surface->num_vertices;j++)
6598 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6599 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6600 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6601 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6602 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6603 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6604 VectorNormalize(normal);
6606 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);
6608 rsurface.svector3f = rsurface.array_deformedsvector3f;
6609 rsurface.svector3f_bufferobject = 0;
6610 rsurface.svector3f_bufferoffset = 0;
6611 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6612 rsurface.tvector3f_bufferobject = 0;
6613 rsurface.tvector3f_bufferoffset = 0;
6614 rsurface.normal3f = rsurface.array_deformednormal3f;
6615 rsurface.normal3f_bufferobject = 0;
6616 rsurface.normal3f_bufferoffset = 0;
6619 // deform vertex array to make wavey water and flags and such
6620 waveparms[0] = deform->waveparms[0];
6621 waveparms[1] = deform->waveparms[1];
6622 waveparms[2] = deform->waveparms[2];
6623 waveparms[3] = deform->waveparms[3];
6624 // this is how a divisor of vertex influence on deformation
6625 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6626 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6627 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6629 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6630 for (j = 0;j < surface->num_vertices;j++)
6632 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6633 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6634 // if the wavefunc depends on time, evaluate it per-vertex
6637 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6638 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6640 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6643 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6644 rsurface.vertex3f_bufferobject = 0;
6645 rsurface.vertex3f_bufferoffset = 0;
6647 case Q3DEFORM_BULGE:
6648 // deform vertex array to make the surface have moving bulges
6649 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6651 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6652 for (j = 0;j < surface->num_vertices;j++)
6654 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6655 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6658 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6659 rsurface.vertex3f_bufferobject = 0;
6660 rsurface.vertex3f_bufferoffset = 0;
6663 // deform vertex array
6664 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6665 VectorScale(deform->parms, scale, waveparms);
6666 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6668 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6669 for (j = 0;j < surface->num_vertices;j++)
6670 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6672 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6673 rsurface.vertex3f_bufferobject = 0;
6674 rsurface.vertex3f_bufferoffset = 0;
6678 // generate texcoords based on the chosen texcoord source
6679 switch(rsurface.texture->tcgen.tcgen)
6682 case Q3TCGEN_TEXTURE:
6683 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6684 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6685 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6687 case Q3TCGEN_LIGHTMAP:
6688 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6689 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6690 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6692 case Q3TCGEN_VECTOR:
6693 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6695 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6696 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)
6698 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6699 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6702 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6703 rsurface.texcoordtexture2f_bufferobject = 0;
6704 rsurface.texcoordtexture2f_bufferoffset = 0;
6706 case Q3TCGEN_ENVIRONMENT:
6707 // make environment reflections using a spheremap
6708 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6710 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6711 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6712 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6713 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6714 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6716 // identical to Q3A's method, but executed in worldspace so
6717 // carried models can be shiny too
6719 float viewer[3], d, reflected[3], worldreflected[3];
6721 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6722 // VectorNormalize(viewer);
6724 d = DotProduct(normal, viewer);
6726 reflected[0] = normal[0]*2*d - viewer[0];
6727 reflected[1] = normal[1]*2*d - viewer[1];
6728 reflected[2] = normal[2]*2*d - viewer[2];
6729 // note: this is proportinal to viewer, so we can normalize later
6731 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6732 VectorNormalize(worldreflected);
6734 // note: this sphere map only uses world x and z!
6735 // so positive and negative y will LOOK THE SAME.
6736 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6737 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6740 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6741 rsurface.texcoordtexture2f_bufferobject = 0;
6742 rsurface.texcoordtexture2f_bufferoffset = 0;
6745 // the only tcmod that needs software vertex processing is turbulent, so
6746 // check for it here and apply the changes if needed
6747 // and we only support that as the first one
6748 // (handling a mixture of turbulent and other tcmods would be problematic
6749 // without punting it entirely to a software path)
6750 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6752 amplitude = rsurface.texture->tcmods[0].parms[1];
6753 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6754 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6756 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6757 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)
6759 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6760 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6763 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6764 rsurface.texcoordtexture2f_bufferobject = 0;
6765 rsurface.texcoordtexture2f_bufferoffset = 0;
6767 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6768 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6769 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6770 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6773 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6776 const msurface_t *surface = texturesurfacelist[0];
6777 const msurface_t *surface2;
6782 // TODO: lock all array ranges before render, rather than on each surface
6783 if (texturenumsurfaces == 1)
6785 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6786 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);
6788 else if (r_batchmode.integer == 2)
6790 #define MAXBATCHTRIANGLES 4096
6791 int batchtriangles = 0;
6792 int batchelements[MAXBATCHTRIANGLES*3];
6793 for (i = 0;i < texturenumsurfaces;i = j)
6795 surface = texturesurfacelist[i];
6797 if (surface->num_triangles > MAXBATCHTRIANGLES)
6799 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);
6802 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6803 batchtriangles = surface->num_triangles;
6804 firstvertex = surface->num_firstvertex;
6805 endvertex = surface->num_firstvertex + surface->num_vertices;
6806 for (;j < texturenumsurfaces;j++)
6808 surface2 = texturesurfacelist[j];
6809 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6811 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6812 batchtriangles += surface2->num_triangles;
6813 firstvertex = min(firstvertex, surface2->num_firstvertex);
6814 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6816 surface2 = texturesurfacelist[j-1];
6817 numvertices = endvertex - firstvertex;
6818 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6821 else if (r_batchmode.integer == 1)
6823 for (i = 0;i < texturenumsurfaces;i = j)
6825 surface = texturesurfacelist[i];
6826 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6827 if (texturesurfacelist[j] != surface2)
6829 surface2 = texturesurfacelist[j-1];
6830 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6831 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6832 GL_LockArrays(surface->num_firstvertex, numvertices);
6833 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6838 for (i = 0;i < texturenumsurfaces;i++)
6840 surface = texturesurfacelist[i];
6841 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6842 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);
6847 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6849 int i, planeindex, vertexindex;
6853 r_waterstate_waterplane_t *p, *bestp;
6854 const msurface_t *surface;
6855 if (r_waterstate.renderingscene)
6857 for (i = 0;i < texturenumsurfaces;i++)
6859 surface = texturesurfacelist[i];
6860 if (lightmaptexunit >= 0)
6861 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6862 if (deluxemaptexunit >= 0)
6863 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6864 // pick the closest matching water plane
6867 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6870 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6872 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6873 d += fabs(PlaneDiff(vert, &p->plane));
6875 if (bestd > d || !bestp)
6883 if (refractiontexunit >= 0)
6884 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6885 if (reflectiontexunit >= 0)
6886 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6890 if (refractiontexunit >= 0)
6891 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6892 if (reflectiontexunit >= 0)
6893 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6895 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6896 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);
6900 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6904 const msurface_t *surface = texturesurfacelist[0];
6905 const msurface_t *surface2;
6910 // TODO: lock all array ranges before render, rather than on each surface
6911 if (texturenumsurfaces == 1)
6913 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6914 if (deluxemaptexunit >= 0)
6915 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6916 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6917 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);
6919 else if (r_batchmode.integer == 2)
6921 #define MAXBATCHTRIANGLES 4096
6922 int batchtriangles = 0;
6923 int batchelements[MAXBATCHTRIANGLES*3];
6924 for (i = 0;i < texturenumsurfaces;i = j)
6926 surface = texturesurfacelist[i];
6927 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6928 if (deluxemaptexunit >= 0)
6929 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6931 if (surface->num_triangles > MAXBATCHTRIANGLES)
6933 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);
6936 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6937 batchtriangles = surface->num_triangles;
6938 firstvertex = surface->num_firstvertex;
6939 endvertex = surface->num_firstvertex + surface->num_vertices;
6940 for (;j < texturenumsurfaces;j++)
6942 surface2 = texturesurfacelist[j];
6943 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6945 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6946 batchtriangles += surface2->num_triangles;
6947 firstvertex = min(firstvertex, surface2->num_firstvertex);
6948 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6950 surface2 = texturesurfacelist[j-1];
6951 numvertices = endvertex - firstvertex;
6952 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6955 else if (r_batchmode.integer == 1)
6958 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6959 for (i = 0;i < texturenumsurfaces;i = j)
6961 surface = texturesurfacelist[i];
6962 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6963 if (texturesurfacelist[j] != surface2)
6965 Con_Printf(" %i", j - i);
6968 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6970 for (i = 0;i < texturenumsurfaces;i = j)
6972 surface = texturesurfacelist[i];
6973 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6974 if (deluxemaptexunit >= 0)
6975 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6976 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6977 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6980 Con_Printf(" %i", j - i);
6982 surface2 = texturesurfacelist[j-1];
6983 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6984 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6985 GL_LockArrays(surface->num_firstvertex, numvertices);
6986 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6994 for (i = 0;i < texturenumsurfaces;i++)
6996 surface = texturesurfacelist[i];
6997 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6998 if (deluxemaptexunit >= 0)
6999 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7000 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7001 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);
7006 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7009 int texturesurfaceindex;
7010 if (r_showsurfaces.integer == 2)
7012 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7014 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7015 for (j = 0;j < surface->num_triangles;j++)
7017 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7018 GL_Color(f, f, f, 1);
7019 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7025 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7027 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7028 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7029 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);
7030 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7031 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);
7036 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7038 int texturesurfaceindex;
7042 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7044 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7045 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)
7053 rsurface.lightmapcolor4f = rsurface.array_color4f;
7054 rsurface.lightmapcolor4f_bufferobject = 0;
7055 rsurface.lightmapcolor4f_bufferoffset = 0;
7058 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7060 int texturesurfaceindex;
7066 if (rsurface.lightmapcolor4f)
7068 // generate color arrays for the surfaces in this list
7069 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7071 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7072 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)
7074 f = RSurf_FogVertex(v);
7084 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7086 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7087 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)
7089 f = RSurf_FogVertex(v);
7097 rsurface.lightmapcolor4f = rsurface.array_color4f;
7098 rsurface.lightmapcolor4f_bufferobject = 0;
7099 rsurface.lightmapcolor4f_bufferoffset = 0;
7102 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7104 int texturesurfaceindex;
7110 if (!rsurface.lightmapcolor4f)
7112 // generate color arrays for the surfaces in this list
7113 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7115 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7116 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)
7118 f = RSurf_FogVertex(v);
7119 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7120 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7121 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7125 rsurface.lightmapcolor4f = rsurface.array_color4f;
7126 rsurface.lightmapcolor4f_bufferobject = 0;
7127 rsurface.lightmapcolor4f_bufferoffset = 0;
7130 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7132 int texturesurfaceindex;
7136 if (!rsurface.lightmapcolor4f)
7138 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7140 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7141 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)
7149 rsurface.lightmapcolor4f = rsurface.array_color4f;
7150 rsurface.lightmapcolor4f_bufferobject = 0;
7151 rsurface.lightmapcolor4f_bufferoffset = 0;
7154 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7156 int texturesurfaceindex;
7160 if (!rsurface.lightmapcolor4f)
7162 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7164 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7165 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)
7167 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7168 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7169 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7173 rsurface.lightmapcolor4f = rsurface.array_color4f;
7174 rsurface.lightmapcolor4f_bufferobject = 0;
7175 rsurface.lightmapcolor4f_bufferoffset = 0;
7178 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7181 rsurface.lightmapcolor4f = NULL;
7182 rsurface.lightmapcolor4f_bufferobject = 0;
7183 rsurface.lightmapcolor4f_bufferoffset = 0;
7184 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7185 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7186 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7187 GL_Color(r, g, b, a);
7188 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7191 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7193 // TODO: optimize applyfog && applycolor case
7194 // just apply fog if necessary, and tint the fog color array if necessary
7195 rsurface.lightmapcolor4f = NULL;
7196 rsurface.lightmapcolor4f_bufferobject = 0;
7197 rsurface.lightmapcolor4f_bufferoffset = 0;
7198 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7199 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7200 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7201 GL_Color(r, g, b, a);
7202 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7205 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7207 int texturesurfaceindex;
7211 if (texturesurfacelist[0]->lightmapinfo)
7213 // generate color arrays for the surfaces in this list
7214 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7216 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7217 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7219 if (surface->lightmapinfo->samples)
7221 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7222 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7223 VectorScale(lm, scale, c);
7224 if (surface->lightmapinfo->styles[1] != 255)
7226 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7228 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7229 VectorMA(c, scale, lm, c);
7230 if (surface->lightmapinfo->styles[2] != 255)
7233 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7234 VectorMA(c, scale, lm, c);
7235 if (surface->lightmapinfo->styles[3] != 255)
7238 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7239 VectorMA(c, scale, lm, c);
7249 rsurface.lightmapcolor4f = rsurface.array_color4f;
7250 rsurface.lightmapcolor4f_bufferobject = 0;
7251 rsurface.lightmapcolor4f_bufferoffset = 0;
7255 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7256 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7257 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7259 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7260 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7261 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7262 GL_Color(r, g, b, a);
7263 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7266 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7268 int texturesurfaceindex;
7275 vec3_t ambientcolor;
7276 vec3_t diffusecolor;
7280 VectorCopy(rsurface.modellight_lightdir, lightdir);
7281 f = 0.5f * r_refdef.lightmapintensity;
7282 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7283 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7284 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7285 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7286 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7287 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7289 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7291 // generate color arrays for the surfaces in this list
7292 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7294 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7295 int numverts = surface->num_vertices;
7296 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7297 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7298 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7299 // q3-style directional shading
7300 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7302 if ((f = DotProduct(n, lightdir)) > 0)
7303 VectorMA(ambientcolor, f, diffusecolor, c);
7305 VectorCopy(ambientcolor, c);
7313 rsurface.lightmapcolor4f = rsurface.array_color4f;
7314 rsurface.lightmapcolor4f_bufferobject = 0;
7315 rsurface.lightmapcolor4f_bufferoffset = 0;
7316 *applycolor = false;
7320 *r = ambientcolor[0];
7321 *g = ambientcolor[1];
7322 *b = ambientcolor[2];
7323 rsurface.lightmapcolor4f = NULL;
7324 rsurface.lightmapcolor4f_bufferobject = 0;
7325 rsurface.lightmapcolor4f_bufferoffset = 0;
7329 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7331 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7332 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7333 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7334 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7335 GL_Color(r, g, b, a);
7336 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7339 void RSurf_SetupDepthAndCulling(void)
7341 // submodels are biased to avoid z-fighting with world surfaces that they
7342 // may be exactly overlapping (avoids z-fighting artifacts on certain
7343 // doors and things in Quake maps)
7344 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7345 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7346 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7347 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7350 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7352 // transparent sky would be ridiculous
7353 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7355 R_SetupGenericShader(false);
7356 skyrenderlater = true;
7357 RSurf_SetupDepthAndCulling();
7359 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7360 // skymasking on them, and Quake3 never did sky masking (unlike
7361 // software Quake and software Quake2), so disable the sky masking
7362 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7363 // and skymasking also looks very bad when noclipping outside the
7364 // level, so don't use it then either.
7365 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7367 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7368 R_Mesh_ColorPointer(NULL, 0, 0);
7369 R_Mesh_ResetTextureState();
7370 if (skyrendermasked)
7372 R_SetupDepthOrShadowShader();
7373 // depth-only (masking)
7374 GL_ColorMask(0,0,0,0);
7375 // just to make sure that braindead drivers don't draw
7376 // anything despite that colormask...
7377 GL_BlendFunc(GL_ZERO, GL_ONE);
7381 R_SetupGenericShader(false);
7383 GL_BlendFunc(GL_ONE, GL_ZERO);
7385 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7386 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7387 if (skyrendermasked)
7388 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7390 R_Mesh_ResetTextureState();
7391 GL_Color(1, 1, 1, 1);
7394 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7396 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7399 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7400 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7401 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7402 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7403 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7404 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7405 if (rsurface.texture->backgroundcurrentskinframe)
7407 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7408 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7409 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7410 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7412 if(rsurface.texture->colormapping)
7414 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7415 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7417 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7418 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7419 R_Mesh_ColorPointer(NULL, 0, 0);
7421 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7423 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7425 // render background
7426 GL_BlendFunc(GL_ONE, GL_ZERO);
7428 GL_AlphaTest(false);
7430 GL_Color(1, 1, 1, 1);
7431 R_Mesh_ColorPointer(NULL, 0, 0);
7433 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7434 if (r_glsl_permutation)
7436 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7437 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7438 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7439 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7440 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7441 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7442 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);
7444 GL_LockArrays(0, 0);
7446 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7447 GL_DepthMask(false);
7448 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7449 R_Mesh_ColorPointer(NULL, 0, 0);
7451 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7452 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7453 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7456 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7457 if (!r_glsl_permutation)
7460 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7461 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7462 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7463 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7464 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7465 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7467 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7469 GL_BlendFunc(GL_ONE, GL_ZERO);
7471 GL_AlphaTest(false);
7475 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7476 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7477 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7480 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7482 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7483 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);
7485 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7489 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7490 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);
7492 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7494 GL_LockArrays(0, 0);
7497 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7499 // OpenGL 1.3 path - anything not completely ancient
7500 int texturesurfaceindex;
7501 qboolean applycolor;
7505 const texturelayer_t *layer;
7506 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7508 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7511 int layertexrgbscale;
7512 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7514 if (layerindex == 0)
7518 GL_AlphaTest(false);
7519 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7522 GL_DepthMask(layer->depthmask && writedepth);
7523 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7524 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7526 layertexrgbscale = 4;
7527 VectorScale(layer->color, 0.25f, layercolor);
7529 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7531 layertexrgbscale = 2;
7532 VectorScale(layer->color, 0.5f, layercolor);
7536 layertexrgbscale = 1;
7537 VectorScale(layer->color, 1.0f, layercolor);
7539 layercolor[3] = layer->color[3];
7540 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7541 R_Mesh_ColorPointer(NULL, 0, 0);
7542 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7543 switch (layer->type)
7545 case TEXTURELAYERTYPE_LITTEXTURE:
7546 memset(&m, 0, sizeof(m));
7547 m.tex[0] = R_GetTexture(r_texture_white);
7548 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7549 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7550 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7551 m.tex[1] = R_GetTexture(layer->texture);
7552 m.texmatrix[1] = layer->texmatrix;
7553 m.texrgbscale[1] = layertexrgbscale;
7554 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7555 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7556 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7557 R_Mesh_TextureState(&m);
7558 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7559 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7560 else if (rsurface.uselightmaptexture)
7561 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7563 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7565 case TEXTURELAYERTYPE_TEXTURE:
7566 memset(&m, 0, sizeof(m));
7567 m.tex[0] = R_GetTexture(layer->texture);
7568 m.texmatrix[0] = layer->texmatrix;
7569 m.texrgbscale[0] = layertexrgbscale;
7570 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7571 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7572 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7573 R_Mesh_TextureState(&m);
7574 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7576 case TEXTURELAYERTYPE_FOG:
7577 memset(&m, 0, sizeof(m));
7578 m.texrgbscale[0] = layertexrgbscale;
7581 m.tex[0] = R_GetTexture(layer->texture);
7582 m.texmatrix[0] = layer->texmatrix;
7583 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7584 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7585 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7587 R_Mesh_TextureState(&m);
7588 // generate a color array for the fog pass
7589 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7590 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7596 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7597 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)
7599 f = 1 - RSurf_FogVertex(v);
7600 c[0] = layercolor[0];
7601 c[1] = layercolor[1];
7602 c[2] = layercolor[2];
7603 c[3] = f * layercolor[3];
7606 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7609 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7611 GL_LockArrays(0, 0);
7614 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7616 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7617 GL_AlphaTest(false);
7621 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7623 // OpenGL 1.1 - crusty old voodoo path
7624 int texturesurfaceindex;
7628 const texturelayer_t *layer;
7629 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7631 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7633 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7635 if (layerindex == 0)
7639 GL_AlphaTest(false);
7640 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7643 GL_DepthMask(layer->depthmask && writedepth);
7644 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7645 R_Mesh_ColorPointer(NULL, 0, 0);
7646 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7647 switch (layer->type)
7649 case TEXTURELAYERTYPE_LITTEXTURE:
7650 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7652 // two-pass lit texture with 2x rgbscale
7653 // first the lightmap pass
7654 memset(&m, 0, sizeof(m));
7655 m.tex[0] = R_GetTexture(r_texture_white);
7656 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7657 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7658 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7659 R_Mesh_TextureState(&m);
7660 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7661 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7662 else if (rsurface.uselightmaptexture)
7663 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7665 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7666 GL_LockArrays(0, 0);
7667 // then apply the texture to it
7668 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7669 memset(&m, 0, sizeof(m));
7670 m.tex[0] = R_GetTexture(layer->texture);
7671 m.texmatrix[0] = layer->texmatrix;
7672 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7673 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7674 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7675 R_Mesh_TextureState(&m);
7676 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);
7680 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7681 memset(&m, 0, sizeof(m));
7682 m.tex[0] = R_GetTexture(layer->texture);
7683 m.texmatrix[0] = layer->texmatrix;
7684 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7685 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7686 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7687 R_Mesh_TextureState(&m);
7688 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7689 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);
7691 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);
7694 case TEXTURELAYERTYPE_TEXTURE:
7695 // singletexture unlit texture with transparency support
7696 memset(&m, 0, sizeof(m));
7697 m.tex[0] = R_GetTexture(layer->texture);
7698 m.texmatrix[0] = layer->texmatrix;
7699 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7700 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7701 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7702 R_Mesh_TextureState(&m);
7703 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);
7705 case TEXTURELAYERTYPE_FOG:
7706 // singletexture fogging
7707 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7710 memset(&m, 0, sizeof(m));
7711 m.tex[0] = R_GetTexture(layer->texture);
7712 m.texmatrix[0] = layer->texmatrix;
7713 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7714 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7715 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7716 R_Mesh_TextureState(&m);
7719 R_Mesh_ResetTextureState();
7720 // generate a color array for the fog pass
7721 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7727 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7728 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)
7730 f = 1 - RSurf_FogVertex(v);
7731 c[0] = layer->color[0];
7732 c[1] = layer->color[1];
7733 c[2] = layer->color[2];
7734 c[3] = f * layer->color[3];
7737 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7740 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7742 GL_LockArrays(0, 0);
7745 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7747 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7748 GL_AlphaTest(false);
7752 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7756 GL_AlphaTest(false);
7757 R_Mesh_ColorPointer(NULL, 0, 0);
7758 R_Mesh_ResetTextureState();
7759 R_SetupGenericShader(false);
7761 if(rsurface.texture && rsurface.texture->currentskinframe)
7763 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7764 c[3] *= rsurface.texture->currentalpha;
7774 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7776 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7777 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7778 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7781 // brighten it up (as texture value 127 means "unlit")
7782 c[0] *= 2 * r_refdef.view.colorscale;
7783 c[1] *= 2 * r_refdef.view.colorscale;
7784 c[2] *= 2 * r_refdef.view.colorscale;
7786 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7787 c[3] *= r_wateralpha.value;
7789 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7791 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7792 GL_DepthMask(false);
7794 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7796 GL_BlendFunc(GL_ONE, GL_ONE);
7797 GL_DepthMask(false);
7799 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7801 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7802 GL_DepthMask(false);
7804 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7806 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7807 GL_DepthMask(false);
7811 GL_BlendFunc(GL_ONE, GL_ZERO);
7812 GL_DepthMask(writedepth);
7815 rsurface.lightmapcolor4f = NULL;
7817 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7819 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7821 rsurface.lightmapcolor4f = NULL;
7822 rsurface.lightmapcolor4f_bufferobject = 0;
7823 rsurface.lightmapcolor4f_bufferoffset = 0;
7825 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7827 qboolean applycolor = true;
7830 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7832 r_refdef.lightmapintensity = 1;
7833 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7834 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7838 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7840 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7841 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7842 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7845 if(!rsurface.lightmapcolor4f)
7846 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7848 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7849 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7850 if(r_refdef.fogenabled)
7851 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7853 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7854 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7857 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7860 RSurf_SetupDepthAndCulling();
7861 if (r_showsurfaces.integer == 3)
7862 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7863 else if (r_glsl.integer && gl_support_fragment_shader)
7864 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7865 else if (gl_combine.integer && r_textureunits.integer >= 2)
7866 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7868 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7872 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7875 RSurf_SetupDepthAndCulling();
7876 if (r_showsurfaces.integer == 3)
7877 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7878 else if (r_glsl.integer && gl_support_fragment_shader)
7879 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7880 else if (gl_combine.integer && r_textureunits.integer >= 2)
7881 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7883 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7887 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7890 int texturenumsurfaces, endsurface;
7892 const msurface_t *surface;
7893 const msurface_t *texturesurfacelist[1024];
7895 // if the model is static it doesn't matter what value we give for
7896 // wantnormals and wanttangents, so this logic uses only rules applicable
7897 // to a model, knowing that they are meaningless otherwise
7898 if (ent == r_refdef.scene.worldentity)
7899 RSurf_ActiveWorldEntity();
7900 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7901 RSurf_ActiveModelEntity(ent, false, false);
7903 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7905 for (i = 0;i < numsurfaces;i = j)
7908 surface = rsurface.modelsurfaces + surfacelist[i];
7909 texture = surface->texture;
7910 rsurface.texture = R_GetCurrentTexture(texture);
7911 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7912 // scan ahead until we find a different texture
7913 endsurface = min(i + 1024, numsurfaces);
7914 texturenumsurfaces = 0;
7915 texturesurfacelist[texturenumsurfaces++] = surface;
7916 for (;j < endsurface;j++)
7918 surface = rsurface.modelsurfaces + surfacelist[j];
7919 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7921 texturesurfacelist[texturenumsurfaces++] = surface;
7923 // render the range of surfaces
7924 if (ent == r_refdef.scene.worldentity)
7925 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7927 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7929 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7930 GL_AlphaTest(false);
7933 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7935 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7939 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7941 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7943 RSurf_SetupDepthAndCulling();
7944 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7945 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7947 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7949 RSurf_SetupDepthAndCulling();
7950 GL_AlphaTest(false);
7951 R_Mesh_ColorPointer(NULL, 0, 0);
7952 R_Mesh_ResetTextureState();
7953 R_SetupGenericShader(false);
7954 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7956 GL_BlendFunc(GL_ONE, GL_ZERO);
7957 GL_Color(0, 0, 0, 1);
7958 GL_DepthTest(writedepth);
7959 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7961 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7963 RSurf_SetupDepthAndCulling();
7964 GL_AlphaTest(false);
7965 R_Mesh_ColorPointer(NULL, 0, 0);
7966 R_Mesh_ResetTextureState();
7967 R_SetupGenericShader(false);
7968 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7970 GL_BlendFunc(GL_ONE, GL_ZERO);
7972 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7974 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7975 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7976 else if (!rsurface.texture->currentnumlayers)
7978 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7980 // transparent surfaces get pushed off into the transparent queue
7981 int surfacelistindex;
7982 const msurface_t *surface;
7983 vec3_t tempcenter, center;
7984 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7986 surface = texturesurfacelist[surfacelistindex];
7987 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7988 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7989 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7990 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7991 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7996 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7997 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8002 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8006 // break the surface list down into batches by texture and use of lightmapping
8007 for (i = 0;i < numsurfaces;i = j)
8010 // texture is the base texture pointer, rsurface.texture is the
8011 // current frame/skin the texture is directing us to use (for example
8012 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8013 // use skin 1 instead)
8014 texture = surfacelist[i]->texture;
8015 rsurface.texture = R_GetCurrentTexture(texture);
8016 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8017 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8019 // if this texture is not the kind we want, skip ahead to the next one
8020 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8024 // simply scan ahead until we find a different texture or lightmap state
8025 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8027 // render the range of surfaces
8028 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
8032 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
8037 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8039 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8041 RSurf_SetupDepthAndCulling();
8042 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8043 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8045 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8047 RSurf_SetupDepthAndCulling();
8048 GL_AlphaTest(false);
8049 R_Mesh_ColorPointer(NULL, 0, 0);
8050 R_Mesh_ResetTextureState();
8051 R_SetupGenericShader(false);
8052 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8054 GL_BlendFunc(GL_ONE, GL_ZERO);
8055 GL_Color(0, 0, 0, 1);
8056 GL_DepthTest(writedepth);
8057 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8059 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8061 RSurf_SetupDepthAndCulling();
8062 GL_AlphaTest(false);
8063 R_Mesh_ColorPointer(NULL, 0, 0);
8064 R_Mesh_ResetTextureState();
8065 R_SetupGenericShader(false);
8066 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8068 GL_BlendFunc(GL_ONE, GL_ZERO);
8070 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8072 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8073 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8074 else if (!rsurface.texture->currentnumlayers)
8076 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8078 // transparent surfaces get pushed off into the transparent queue
8079 int surfacelistindex;
8080 const msurface_t *surface;
8081 vec3_t tempcenter, center;
8082 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8084 surface = texturesurfacelist[surfacelistindex];
8085 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8086 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8087 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8088 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8089 if (queueentity->transparent_offset) // transparent offset
8091 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8092 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8093 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8095 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8100 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8101 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8106 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8110 // break the surface list down into batches by texture and use of lightmapping
8111 for (i = 0;i < numsurfaces;i = j)
8114 // texture is the base texture pointer, rsurface.texture is the
8115 // current frame/skin the texture is directing us to use (for example
8116 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8117 // use skin 1 instead)
8118 texture = surfacelist[i]->texture;
8119 rsurface.texture = R_GetCurrentTexture(texture);
8120 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8121 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8123 // if this texture is not the kind we want, skip ahead to the next one
8124 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8128 // simply scan ahead until we find a different texture or lightmap state
8129 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8131 // render the range of surfaces
8132 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8136 float locboxvertex3f[6*4*3] =
8138 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8139 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8140 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8141 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8142 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8143 1,0,0, 0,0,0, 0,1,0, 1,1,0
8146 unsigned short locboxelements[6*2*3] =
8156 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8159 cl_locnode_t *loc = (cl_locnode_t *)ent;
8161 float vertex3f[6*4*3];
8163 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8164 GL_DepthMask(false);
8165 GL_DepthRange(0, 1);
8166 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8168 GL_CullFace(GL_NONE);
8169 R_Mesh_Matrix(&identitymatrix);
8171 R_Mesh_VertexPointer(vertex3f, 0, 0);
8172 R_Mesh_ColorPointer(NULL, 0, 0);
8173 R_Mesh_ResetTextureState();
8174 R_SetupGenericShader(false);
8177 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8178 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8179 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8180 surfacelist[0] < 0 ? 0.5f : 0.125f);
8182 if (VectorCompare(loc->mins, loc->maxs))
8184 VectorSet(size, 2, 2, 2);
8185 VectorMA(loc->mins, -0.5f, size, mins);
8189 VectorCopy(loc->mins, mins);
8190 VectorSubtract(loc->maxs, loc->mins, size);
8193 for (i = 0;i < 6*4*3;)
8194 for (j = 0;j < 3;j++, i++)
8195 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8197 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8200 void R_DrawLocs(void)
8203 cl_locnode_t *loc, *nearestloc;
8205 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8206 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8208 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8209 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8213 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8215 if (decalsystem->decals)
8216 Mem_Free(decalsystem->decals);
8217 memset(decalsystem, 0, sizeof(*decalsystem));
8220 void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex)
8231 // expand or initialize the system
8232 if (decalsystem->maxdecals <= decalsystem->numdecals)
8234 decalsystem_t old = *decalsystem;
8235 qboolean useshortelements;
8236 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8237 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8238 decalsystem->decals = Mem_Alloc(cls.levelmempool, decalsystem->maxdecals * (sizeof(tridecal_t) + sizeof(float[3][3]) + sizeof(float[3][2]) + sizeof(float[3][4]) + sizeof(int[3]) + (useshortelements ? sizeof(unsigned short[3]) : 0)));
8239 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8240 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8241 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8242 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8243 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8244 if (decalsystem->numdecals)
8246 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8247 memcpy(decalsystem->vertex3f, old.vertex3f, decalsystem->numdecals * sizeof(float[3][3]));
8248 memcpy(decalsystem->texcoord2f, old.texcoord2f, decalsystem->numdecals * sizeof(float[3][2]));
8249 memcpy(decalsystem->color4f, old.color4f, decalsystem->numdecals * sizeof(float[3][4]));
8251 Mem_Free(old.decals);
8252 for (i = 0;i < decalsystem->maxdecals*3;i++)
8253 decalsystem->element3i[i] = i;
8254 if (useshortelements)
8255 for (i = 0;i < decalsystem->maxdecals*3;i++)
8256 decalsystem->element3s[i] = i;
8259 // grab a decal and search for another free slot for the next one
8260 maxdecals = decalsystem->maxdecals;
8261 decals = decalsystem->decals;
8262 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8263 v3f = decalsystem->vertex3f + 9*i;
8264 tc2f = decalsystem->texcoord2f + 6*i;
8265 c4f = decalsystem->color4f + 12*i;
8266 for (i = decalsystem->freedecal;i < maxdecals && decals[i].colors[0][3];i++)
8268 decalsystem->freedecal = i;
8269 if (decalsystem->numdecals <= i)
8270 decalsystem->numdecals = i + 1;
8272 // initialize the decal
8274 decal->triangleindex = triangleindex;
8275 decal->colors[0][0] = (unsigned char)(c0[0]*255.0f);
8276 decal->colors[0][1] = (unsigned char)(c0[1]*255.0f);
8277 decal->colors[0][2] = (unsigned char)(c0[2]*255.0f);
8278 decal->colors[0][3] = 255;
8279 decal->colors[1][0] = (unsigned char)(c1[0]*255.0f);
8280 decal->colors[1][1] = (unsigned char)(c1[1]*255.0f);
8281 decal->colors[1][2] = (unsigned char)(c1[2]*255.0f);
8282 decal->colors[1][3] = 255;
8283 decal->colors[2][0] = (unsigned char)(c2[0]*255.0f);
8284 decal->colors[2][1] = (unsigned char)(c2[1]*255.0f);
8285 decal->colors[2][2] = (unsigned char)(c2[2]*255.0f);
8286 decal->colors[2][3] = 255;
8303 c4f[ 0] = decal->colors[0][0] * ca;
8304 c4f[ 1] = decal->colors[0][1] * ca;
8305 c4f[ 2] = decal->colors[0][2] * ca;
8307 c4f[ 4] = decal->colors[1][0] * ca;
8308 c4f[ 5] = decal->colors[1][1] * ca;
8309 c4f[ 6] = decal->colors[1][2] * ca;
8311 c4f[ 8] = decal->colors[2][0] * ca;
8312 c4f[ 9] = decal->colors[2][1] * ca;
8313 c4f[10] = decal->colors[2][2] * ca;
8317 extern cvar_t cl_decals_bias;
8318 extern cvar_t cl_decals_models;
8319 void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
8321 matrix4x4_t projection;
8322 decalsystem_t *decalsystem;
8325 const float *vertex3f;
8326 const msurface_t *surface;
8327 const msurface_t *surfaces;
8328 const int *surfacelist;
8329 const texture_t *texture;
8333 int surfacelistindex;
8339 float localorigin[3];
8340 float localnormal[3];
8351 float points[2][9][3];
8355 decalsystem = &ent->decalsystem;
8357 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8359 R_DecalSystem_Reset(&ent->decalsystem);
8363 if (!model->brush.data_nodes && !cl_decals_models.integer)
8365 if (decalsystem->model)
8366 R_DecalSystem_Reset(decalsystem);
8370 if (decalsystem->model != model)
8371 R_DecalSystem_Reset(decalsystem);
8372 decalsystem->model = model;
8374 RSurf_ActiveModelEntity(ent, false, false);
8376 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8377 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8378 VectorNormalize(localnormal);
8379 localsize = worldsize*rsurface.inversematrixscale;
8380 ilocalsize = 1.0f / localsize;
8381 localmins[0] = localorigin[0] - localsize;
8382 localmins[1] = localorigin[1] - localsize;
8383 localmins[2] = localorigin[2] - localsize;
8384 localmaxs[0] = localorigin[0] + localsize;
8385 localmaxs[1] = localorigin[1] + localsize;
8386 localmaxs[2] = localorigin[2] + localsize;
8388 //VectorCopy(localnormal, planes[4]);
8389 //VectorVectors(planes[4], planes[2], planes[0]);
8390 AnglesFromVectors(angles, localnormal, NULL, false);
8391 AngleVectors(angles, planes[0], planes[2], planes[4]);
8392 VectorNegate(planes[0], planes[1]);
8393 VectorNegate(planes[2], planes[3]);
8394 VectorNegate(planes[4], planes[5]);
8395 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8396 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8397 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8398 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8399 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8400 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8405 matrix4x4_t forwardprojection;
8406 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8407 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8412 float projectionvector[4][3];
8413 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8414 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8415 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8416 projectionvector[0][0] = planes[0][0] * ilocalsize;
8417 projectionvector[0][1] = planes[1][0] * ilocalsize;
8418 projectionvector[0][2] = planes[2][0] * ilocalsize;
8419 projectionvector[1][0] = planes[0][1] * ilocalsize;
8420 projectionvector[1][1] = planes[1][1] * ilocalsize;
8421 projectionvector[1][2] = planes[2][1] * ilocalsize;
8422 projectionvector[2][0] = planes[0][2] * ilocalsize;
8423 projectionvector[2][1] = planes[1][2] * ilocalsize;
8424 projectionvector[2][2] = planes[2][2] * ilocalsize;
8425 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8426 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8427 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8428 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8432 dynamic = model->surfmesh.isanimated;
8433 vertex3f = rsurface.modelvertex3f;
8434 numsurfacelist = model->nummodelsurfaces;
8435 surfacelist = model->sortedmodelsurfaces;
8436 surfaces = model->data_surfaces;
8437 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8439 surface = surfaces + surfacelist[surfacelistindex];
8440 // skip transparent surfaces
8441 texture = surface->texture;
8442 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8444 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8446 if (texture->currentalpha < 1)
8448 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8450 numvertices = surface->num_vertices;
8451 numtriangles = surface->num_triangles;
8452 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8454 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8456 index = 3*e[cornerindex];
8457 VectorCopy(vertex3f + index, v[cornerindex]);
8460 //TriangleNormal(v[0], v[1], v[2], normal);
8461 //if (DotProduct(normal, localnormal) < 0.0f)
8463 // clip by each of the box planes formed from the projection matrix
8464 // if anything survives, we emit the decal
8465 numpoints = PolygonF_Clip(3 , v[0] , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
8468 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
8471 numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
8474 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
8477 numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
8480 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
8483 // some part of the triangle survived, so we have to accept it...
8486 // dynamic always uses the original triangle
8488 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8490 index = 3*e[cornerindex];
8491 VectorCopy(vertex3f + index, v[cornerindex]);
8494 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8496 // convert vertex positions to texcoords
8497 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8498 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8499 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8500 // calculate distance fade from the projection origin
8501 f = a * (1.0f-fabs(temp[0]));
8503 c[cornerindex][0] = r * f;
8504 c[cornerindex][1] = g * f;
8505 c[cornerindex][2] = b * f;
8506 c[cornerindex][3] = 1.0f;
8507 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8510 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex);
8512 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8513 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1);
8518 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
8520 int renderentityindex;
8523 entity_render_t *ent;
8525 worldmins[0] = worldorigin[0] - worldsize;
8526 worldmins[1] = worldorigin[1] - worldsize;
8527 worldmins[2] = worldorigin[2] - worldsize;
8528 worldmaxs[0] = worldorigin[0] + worldsize;
8529 worldmaxs[1] = worldorigin[1] + worldsize;
8530 worldmaxs[2] = worldorigin[2] + worldsize;
8532 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8534 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8536 ent = r_refdef.scene.entities[renderentityindex];
8537 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8540 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8544 extern skinframe_t *decalskinframe;
8545 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8548 decalsystem_t *decalsystem = &ent->decalsystem;
8559 if (!decalsystem->numdecals)
8562 if (r_showsurfaces.integer)
8565 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8567 R_DecalSystem_Reset(decalsystem);
8571 // if the model is static it doesn't matter what value we give for
8572 // wantnormals and wanttangents, so this logic uses only rules applicable
8573 // to a model, knowing that they are meaningless otherwise
8574 if (ent == r_refdef.scene.worldentity)
8575 RSurf_ActiveWorldEntity();
8577 RSurf_ActiveModelEntity(ent, false, false);
8579 if (decalsystem->lastupdatetime)
8580 frametime = cl.time - decalsystem->lastupdatetime;
8583 decalsystem->lastupdatetime = cl.time;
8584 decal = decalsystem->decals;
8585 numdecals = decalsystem->numdecals;
8587 fadedelay = cl_decals_time.value;
8588 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
8590 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8592 if (!decal->colors[0][3])
8595 decal->lived += frametime;
8596 if (decal->lived >= fadedelay)
8598 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
8601 // kill the decal by zeroing vertex data
8602 memset(decalsystem->vertex3f + 9*i, 0, sizeof(float[3][3]));
8603 memset(decalsystem->texcoord2f + 6*i, 0, sizeof(float[3][2]));
8604 memset(decalsystem->color4f + 12*i, 0, sizeof(float[3][4]));
8605 memset(decal, 0, sizeof(*decal));
8606 if (decalsystem->freedecal > i)
8607 decalsystem->freedecal = i;
8611 // update color values for fading decals
8612 alpha *= (1.0f/255.0f);
8613 c4f = decalsystem->color4f + 12*i;
8614 c4f[ 0] = decal->colors[0][0] * alpha;
8615 c4f[ 1] = decal->colors[0][1] * alpha;
8616 c4f[ 2] = decal->colors[0][2] * alpha;
8618 c4f[ 4] = decal->colors[1][0] * alpha;
8619 c4f[ 5] = decal->colors[1][1] * alpha;
8620 c4f[ 6] = decal->colors[1][2] * alpha;
8622 c4f[ 8] = decal->colors[2][0] * alpha;
8623 c4f[ 9] = decal->colors[2][1] * alpha;
8624 c4f[10] = decal->colors[2][2] * alpha;
8628 // update vertex positions for animated models
8629 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8631 e = rsurface.modelelement3i + 3*decal->triangleindex;
8632 v3f = decalsystem->vertex3f + 9*i;
8633 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8634 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8635 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8639 // reduce numdecals if possible
8640 while (numdecals > 0 && !decalsystem->decals[numdecals - 1].colors[0][3])
8642 decalsystem->numdecals = numdecals;
8646 r_refdef.stats.decals += numdecals;
8647 // now render the decals all at once
8648 // (this assumes they all use one particle font texture!)
8649 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numdecals, decalsystem->element3i, decalsystem->element3s, false, false);
8650 R_Mesh_ResetTextureState();
8651 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8652 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8653 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8654 R_SetupGenericShader(true);
8655 GL_DepthMask(false);
8656 GL_DepthRange(0, 1);
8657 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
8659 GL_CullFace(GL_NONE);
8660 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8661 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8662 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8663 GL_LockArrays(0, numdecals * 3);
8664 R_Mesh_Draw(0, numdecals * 3, 0, numdecals, decalsystem->element3i, decalsystem->element3s, 0, 0);
8665 GL_LockArrays(0, 0);
8670 // if there are no decals left, reset decalsystem
8671 R_DecalSystem_Reset(decalsystem);
8675 void R_DrawDebugModel(void)
8677 entity_render_t *ent = rsurface.entity;
8678 int i, j, k, l, flagsmask;
8679 const int *elements;
8681 const msurface_t *surface;
8682 dp_model_t *model = ent->model;
8685 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8687 R_Mesh_ColorPointer(NULL, 0, 0);
8688 R_Mesh_ResetTextureState();
8689 R_SetupGenericShader(false);
8690 GL_DepthRange(0, 1);
8691 GL_DepthTest(!r_showdisabledepthtest.integer);
8692 GL_DepthMask(false);
8693 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8695 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8697 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8698 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8700 if (brush->colbrushf && brush->colbrushf->numtriangles)
8702 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8703 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);
8704 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8707 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8709 if (surface->num_collisiontriangles)
8711 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8712 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);
8713 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8718 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8720 if (r_showtris.integer || r_shownormals.integer)
8722 if (r_showdisabledepthtest.integer)
8724 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8725 GL_DepthMask(false);
8729 GL_BlendFunc(GL_ONE, GL_ZERO);
8732 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8734 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8736 rsurface.texture = R_GetCurrentTexture(surface->texture);
8737 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8739 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8740 if (r_showtris.value > 0)
8742 if (!rsurface.texture->currentlayers->depthmask)
8743 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8744 else if (ent == r_refdef.scene.worldentity)
8745 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8747 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8748 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8749 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8750 R_Mesh_ColorPointer(NULL, 0, 0);
8751 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8752 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8753 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8754 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);
8755 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8758 if (r_shownormals.value < 0)
8761 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8763 VectorCopy(rsurface.vertex3f + l * 3, v);
8764 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8765 qglVertex3f(v[0], v[1], v[2]);
8766 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8767 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8768 qglVertex3f(v[0], v[1], v[2]);
8773 if (r_shownormals.value > 0)
8776 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8778 VectorCopy(rsurface.vertex3f + l * 3, v);
8779 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8780 qglVertex3f(v[0], v[1], v[2]);
8781 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8782 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8783 qglVertex3f(v[0], v[1], v[2]);
8788 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8790 VectorCopy(rsurface.vertex3f + l * 3, v);
8791 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8792 qglVertex3f(v[0], v[1], v[2]);
8793 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8794 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8795 qglVertex3f(v[0], v[1], v[2]);
8800 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8802 VectorCopy(rsurface.vertex3f + l * 3, v);
8803 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8804 qglVertex3f(v[0], v[1], v[2]);
8805 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8806 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8807 qglVertex3f(v[0], v[1], v[2]);
8814 rsurface.texture = NULL;
8818 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8819 int r_maxsurfacelist = 0;
8820 const msurface_t **r_surfacelist = NULL;
8821 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8823 int i, j, endj, f, flagsmask;
8825 dp_model_t *model = r_refdef.scene.worldmodel;
8826 msurface_t *surfaces;
8827 unsigned char *update;
8828 int numsurfacelist = 0;
8832 if (r_maxsurfacelist < model->num_surfaces)
8834 r_maxsurfacelist = model->num_surfaces;
8836 Mem_Free(r_surfacelist);
8837 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8840 RSurf_ActiveWorldEntity();
8842 surfaces = model->data_surfaces;
8843 update = model->brushq1.lightmapupdateflags;
8845 // update light styles on this submodel
8846 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8848 model_brush_lightstyleinfo_t *style;
8849 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8851 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8853 int *list = style->surfacelist;
8854 style->value = r_refdef.scene.lightstylevalue[style->style];
8855 for (j = 0;j < style->numsurfaces;j++)
8856 update[list[j]] = true;
8861 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8866 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8872 rsurface.uselightmaptexture = false;
8873 rsurface.texture = NULL;
8874 rsurface.rtlight = NULL;
8876 // add visible surfaces to draw list
8877 for (i = 0;i < model->nummodelsurfaces;i++)
8879 j = model->sortedmodelsurfaces[i];
8880 if (r_refdef.viewcache.world_surfacevisible[j])
8881 r_surfacelist[numsurfacelist++] = surfaces + j;
8883 // update lightmaps if needed
8885 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8886 if (r_refdef.viewcache.world_surfacevisible[j])
8888 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8889 // don't do anything if there were no surfaces
8890 if (!numsurfacelist)
8892 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8895 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8896 GL_AlphaTest(false);
8898 // add to stats if desired
8899 if (r_speeds.integer && !skysurfaces && !depthonly)
8901 r_refdef.stats.world_surfaces += numsurfacelist;
8902 for (j = 0;j < numsurfacelist;j++)
8903 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8906 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8909 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8911 int i, j, endj, f, flagsmask;
8913 dp_model_t *model = ent->model;
8914 msurface_t *surfaces;
8915 unsigned char *update;
8916 int numsurfacelist = 0;
8920 if (r_maxsurfacelist < model->num_surfaces)
8922 r_maxsurfacelist = model->num_surfaces;
8924 Mem_Free(r_surfacelist);
8925 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8928 // if the model is static it doesn't matter what value we give for
8929 // wantnormals and wanttangents, so this logic uses only rules applicable
8930 // to a model, knowing that they are meaningless otherwise
8931 if (ent == r_refdef.scene.worldentity)
8932 RSurf_ActiveWorldEntity();
8933 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8934 RSurf_ActiveModelEntity(ent, false, false);
8936 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8938 surfaces = model->data_surfaces;
8939 update = model->brushq1.lightmapupdateflags;
8941 // update light styles
8942 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8944 model_brush_lightstyleinfo_t *style;
8945 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8947 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8949 int *list = style->surfacelist;
8950 style->value = r_refdef.scene.lightstylevalue[style->style];
8951 for (j = 0;j < style->numsurfaces;j++)
8952 update[list[j]] = true;
8957 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8962 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8968 rsurface.uselightmaptexture = false;
8969 rsurface.texture = NULL;
8970 rsurface.rtlight = NULL;
8972 // add visible surfaces to draw list
8973 for (i = 0;i < model->nummodelsurfaces;i++)
8974 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8975 // don't do anything if there were no surfaces
8976 if (!numsurfacelist)
8978 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8981 // update lightmaps if needed
8983 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8985 R_BuildLightMap(ent, surfaces + j);
8986 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8987 GL_AlphaTest(false);
8989 // add to stats if desired
8990 if (r_speeds.integer && !skysurfaces && !depthonly)
8992 r_refdef.stats.entities_surfaces += numsurfacelist;
8993 for (j = 0;j < numsurfacelist;j++)
8994 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8997 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9000 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
9002 static texture_t texture;
9003 static msurface_t surface;
9004 const msurface_t *surfacelist = &surface;
9006 // fake enough texture and surface state to render this geometry
9008 texture.update_lastrenderframe = -1; // regenerate this texture
9009 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9010 texture.currentskinframe = skinframe;
9011 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9012 texture.specularscalemod = 1;
9013 texture.specularpowermod = 1;
9015 surface.texture = &texture;
9016 surface.num_triangles = numtriangles;
9017 surface.num_firsttriangle = firsttriangle;
9018 surface.num_vertices = numvertices;
9019 surface.num_firstvertex = firstvertex;
9022 rsurface.texture = R_GetCurrentTexture(surface.texture);
9023 rsurface.uselightmaptexture = false;
9024 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);