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
33 qboolean r_loadnormalmap;
42 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
43 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
44 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
45 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
46 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)"};
47 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
48 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
49 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
51 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
52 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"};
53 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
54 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)"};
55 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
57 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
59 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"};
60 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
61 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
62 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
63 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
64 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
65 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)"};
66 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
67 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
68 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"};
69 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"};
70 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
71 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"};
72 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"};
73 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"};
74 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
75 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
76 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
77 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
78 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
79 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
80 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
81 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
82 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
83 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
84 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
85 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
86 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
87 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."};
88 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
89 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
90 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
91 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."};
92 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
93 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
94 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"};
95 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"};
96 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
97 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
99 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
102 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
103 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
104 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
105 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
106 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
107 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
108 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
110 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)"};
112 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
113 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)"};
114 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
115 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
116 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
117 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
118 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)"};
119 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)"};
120 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)"};
121 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)"};
122 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)"};
124 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)"};
125 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
126 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"};
127 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
128 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
130 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
131 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
132 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
133 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
135 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
136 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
137 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
138 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
139 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
140 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
141 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
143 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
144 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
145 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
146 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)"};
148 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"};
150 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"};
152 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
154 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
155 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
156 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"};
157 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
158 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
159 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
160 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
162 extern cvar_t v_glslgamma;
164 extern qboolean v_flipped_state;
166 static struct r_bloomstate_s
171 int bloomwidth, bloomheight;
173 int screentexturewidth, screentextureheight;
174 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
176 int bloomtexturewidth, bloomtextureheight;
177 rtexture_t *texture_bloom;
179 // arrays for rendering the screen passes
180 float screentexcoord2f[8];
181 float bloomtexcoord2f[8];
182 float offsettexcoord2f[8];
184 r_viewport_t viewport;
188 r_waterstate_t r_waterstate;
190 /// shadow volume bsp struct with automatically growing nodes buffer
193 rtexture_t *r_texture_blanknormalmap;
194 rtexture_t *r_texture_white;
195 rtexture_t *r_texture_grey128;
196 rtexture_t *r_texture_black;
197 rtexture_t *r_texture_notexture;
198 rtexture_t *r_texture_whitecube;
199 rtexture_t *r_texture_normalizationcube;
200 rtexture_t *r_texture_fogattenuation;
201 rtexture_t *r_texture_gammaramps;
202 unsigned int r_texture_gammaramps_serial;
203 //rtexture_t *r_texture_fogintensity;
205 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
206 unsigned int r_numqueries;
207 unsigned int r_maxqueries;
209 typedef struct r_qwskincache_s
211 char name[MAX_QPATH];
212 skinframe_t *skinframe;
216 static r_qwskincache_t *r_qwskincache;
217 static int r_qwskincache_size;
219 /// vertex coordinates for a quad that covers the screen exactly
220 const float r_screenvertex3f[12] =
228 extern void R_DrawModelShadows(void);
230 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
233 for (i = 0;i < verts;i++)
244 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
247 for (i = 0;i < verts;i++)
257 // FIXME: move this to client?
260 if (gamemode == GAME_NEHAHRA)
262 Cvar_Set("gl_fogenable", "0");
263 Cvar_Set("gl_fogdensity", "0.2");
264 Cvar_Set("gl_fogred", "0.3");
265 Cvar_Set("gl_foggreen", "0.3");
266 Cvar_Set("gl_fogblue", "0.3");
268 r_refdef.fog_density = 0;
269 r_refdef.fog_red = 0;
270 r_refdef.fog_green = 0;
271 r_refdef.fog_blue = 0;
272 r_refdef.fog_alpha = 1;
273 r_refdef.fog_start = 0;
274 r_refdef.fog_end = 16384;
275 r_refdef.fog_height = 1<<30;
276 r_refdef.fog_fadedepth = 128;
279 static void R_BuildBlankTextures(void)
281 unsigned char data[4];
282 data[2] = 128; // normal X
283 data[1] = 128; // normal Y
284 data[0] = 255; // normal Z
285 data[3] = 128; // height
286 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
291 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
296 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
301 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
304 static void R_BuildNoTexture(void)
307 unsigned char pix[16][16][4];
308 // this makes a light grey/dark grey checkerboard texture
309 for (y = 0;y < 16;y++)
311 for (x = 0;x < 16;x++)
313 if ((y < 8) ^ (x < 8))
329 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
332 static void R_BuildWhiteCube(void)
334 unsigned char data[6*1*1*4];
335 memset(data, 255, sizeof(data));
336 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
339 static void R_BuildNormalizationCube(void)
343 vec_t s, t, intensity;
345 unsigned char data[6][NORMSIZE][NORMSIZE][4];
346 for (side = 0;side < 6;side++)
348 for (y = 0;y < NORMSIZE;y++)
350 for (x = 0;x < NORMSIZE;x++)
352 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
353 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
388 intensity = 127.0f / sqrt(DotProduct(v, v));
389 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
390 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
391 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
392 data[side][y][x][3] = 255;
396 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
399 static void R_BuildFogTexture(void)
403 unsigned char data1[FOGWIDTH][4];
404 //unsigned char data2[FOGWIDTH][4];
407 r_refdef.fogmasktable_start = r_refdef.fog_start;
408 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
409 r_refdef.fogmasktable_range = r_refdef.fogrange;
410 r_refdef.fogmasktable_density = r_refdef.fog_density;
412 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
413 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
415 d = (x * r - r_refdef.fogmasktable_start);
416 if(developer.integer >= 100)
417 Con_Printf("%f ", d);
419 if (r_fog_exp2.integer)
420 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
422 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
423 if(developer.integer >= 100)
424 Con_Printf(" : %f ", alpha);
425 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
426 if(developer.integer >= 100)
427 Con_Printf(" = %f\n", alpha);
428 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
431 for (x = 0;x < FOGWIDTH;x++)
433 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
438 //data2[x][0] = 255 - b;
439 //data2[x][1] = 255 - b;
440 //data2[x][2] = 255 - b;
443 if (r_texture_fogattenuation)
445 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
446 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
450 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);
451 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
455 static const char *builtinshaderstring =
456 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
457 "// written by Forest 'LordHavoc' Hale\n"
459 "// enable various extensions depending on permutation:\n"
461 "#ifdef USESHADOWMAPRECT\n"
462 "# extension GL_ARB_texture_rectangle : enable\n"
465 "#ifdef USESHADOWMAP2D\n"
466 "# ifdef GL_EXT_gpu_shader4\n"
467 "# extension GL_EXT_gpu_shader4 : enable\n"
469 "# ifdef GL_ARB_texture_gather\n"
470 "# extension GL_ARB_texture_gather : enable\n"
472 "# ifdef GL_AMD_texture_texture4\n"
473 "# extension GL_AMD_texture_texture4 : enable\n"
478 "#ifdef USESHADOWMAPCUBE\n"
479 "# extension GL_EXT_gpu_shader4 : enable\n"
482 "#ifdef USESHADOWSAMPLER\n"
483 "# extension GL_ARB_shadow : enable\n"
486 "// common definitions between vertex shader and fragment shader:\n"
488 "//#ifdef __GLSL_CG_DATA_TYPES\n"
489 "//# define myhalf half\n"
490 "//# define myhalf2 half2\n"
491 "//# define myhalf3half3\n"
492 "//# define myhalf4 half4\n"
494 "# define myhalf float\n"
495 "# define myhalf2 vec2\n"
496 "# define myhalf3 vec3\n"
497 "# define myhalf4 vec4\n"
500 "#ifdef USEFOGINSIDE\n"
503 "# ifdef USEFOGOUTSIDE\n"
508 "#ifdef MODE_DEPTH_OR_SHADOW\n"
510 "# ifdef VERTEX_SHADER\n"
513 " gl_Position = ftransform();\n"
518 "#ifdef MODE_SHOWDEPTH\n"
519 "# ifdef VERTEX_SHADER\n"
522 " gl_Position = ftransform();\n"
523 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
526 "# ifdef FRAGMENT_SHADER\n"
529 " gl_FragColor = gl_Color;\n"
533 "#else // !MODE_SHOWDEPTH\n"
535 "#ifdef MODE_POSTPROCESS\n"
536 "# ifdef VERTEX_SHADER\n"
539 " gl_FrontColor = gl_Color;\n"
540 " gl_Position = ftransform();\n"
541 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
543 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
547 "# ifdef FRAGMENT_SHADER\n"
549 "uniform sampler2D Texture_First;\n"
551 "uniform sampler2D Texture_Second;\n"
553 "#ifdef USEGAMMARAMPS\n"
554 "uniform sampler2D Texture_GammaRamps;\n"
556 "#ifdef USESATURATION\n"
557 "uniform float Saturation;\n"
559 "#ifdef USEVIEWTINT\n"
560 "uniform vec4 TintColor;\n"
562 "//uncomment these if you want to use them:\n"
563 "uniform vec4 UserVec1;\n"
564 "// uniform vec4 UserVec2;\n"
565 "// uniform vec4 UserVec3;\n"
566 "// uniform vec4 UserVec4;\n"
567 "// uniform float ClientTime;\n"
568 "uniform vec2 PixelSize;\n"
571 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
573 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
575 "#ifdef USEVIEWTINT\n"
576 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
579 "#ifdef USEPOSTPROCESSING\n"
580 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
581 "// 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"
582 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
583 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
584 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
585 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
586 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
587 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
590 "#ifdef USESATURATION\n"
591 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
592 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
593 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
594 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
597 "#ifdef USEGAMMARAMPS\n"
598 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
599 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
600 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
607 "#ifdef MODE_GENERIC\n"
608 "# ifdef VERTEX_SHADER\n"
611 " gl_FrontColor = gl_Color;\n"
612 "# ifdef USEDIFFUSE\n"
613 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
615 "# ifdef USESPECULAR\n"
616 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
618 " gl_Position = ftransform();\n"
621 "# ifdef FRAGMENT_SHADER\n"
623 "# ifdef USEDIFFUSE\n"
624 "uniform sampler2D Texture_First;\n"
626 "# ifdef USESPECULAR\n"
627 "uniform sampler2D Texture_Second;\n"
632 " gl_FragColor = gl_Color;\n"
633 "# ifdef USEDIFFUSE\n"
634 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
637 "# ifdef USESPECULAR\n"
638 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
640 "# ifdef USECOLORMAPPING\n"
641 " gl_FragColor *= tex2;\n"
644 " gl_FragColor += tex2;\n"
646 "# ifdef USEVERTEXTEXTUREBLEND\n"
647 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
652 "#else // !MODE_GENERIC\n"
653 "#ifdef MODE_BLOOMBLUR\n"
654 "# ifdef VERTEX_SHADER\n"
657 " gl_FrontColor = gl_Color;\n"
658 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
659 " gl_Position = ftransform();\n"
662 "# ifdef FRAGMENT_SHADER\n"
664 "uniform sampler2D Texture_First;\n"
665 "uniform vec4 BloomBlur_Parameters;\n"
670 " vec2 tc = gl_TexCoord[0].xy;\n"
671 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
672 " tc += BloomBlur_Parameters.xy;\n"
673 " for (i = 1;i < SAMPLES;i++)\n"
675 " color += texture2D(Texture_First, tc).rgb;\n"
676 " tc += BloomBlur_Parameters.xy;\n"
678 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
682 "#else // !MODE_BLOOMBLUR\n"
684 "varying vec2 TexCoord;\n"
685 "#ifdef USEVERTEXTEXTUREBLEND\n"
686 "varying vec2 TexCoord2;\n"
688 "varying vec2 TexCoordLightmap;\n"
690 "#ifdef MODE_LIGHTSOURCE\n"
691 "varying vec3 CubeVector;\n"
694 "#ifdef MODE_LIGHTSOURCE\n"
695 "varying vec3 LightVector;\n"
697 "#ifdef MODE_LIGHTDIRECTION\n"
698 "varying vec3 LightVector;\n"
701 "varying vec3 EyeVector;\n"
703 "varying vec3 EyeVectorModelSpace;\n"
704 "varying float FogPlaneVertexDist;\n"
707 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
708 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
709 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
711 "#ifdef MODE_WATER\n"
712 "varying vec4 ModelViewProjectionPosition;\n"
714 "#ifdef MODE_REFRACTION\n"
715 "varying vec4 ModelViewProjectionPosition;\n"
717 "#ifdef USEREFLECTION\n"
718 "varying vec4 ModelViewProjectionPosition;\n"
725 "// vertex shader specific:\n"
726 "#ifdef VERTEX_SHADER\n"
728 "uniform vec3 LightPosition;\n"
729 "uniform vec3 EyePosition;\n"
730 "uniform vec3 LightDir;\n"
731 "uniform vec4 FogPlane;\n"
733 "// 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"
737 " gl_FrontColor = gl_Color;\n"
738 " // copy the surface texcoord\n"
739 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
740 "#ifdef USEVERTEXTEXTUREBLEND\n"
741 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
743 "#ifndef MODE_LIGHTSOURCE\n"
744 "# ifndef MODE_LIGHTDIRECTION\n"
745 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
749 "#ifdef MODE_LIGHTSOURCE\n"
750 " // transform vertex position into light attenuation/cubemap space\n"
751 " // (-1 to +1 across the light box)\n"
752 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
754 " // transform unnormalized light direction into tangent space\n"
755 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
756 " // normalize it per pixel)\n"
757 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
758 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
759 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
760 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
763 "#ifdef MODE_LIGHTDIRECTION\n"
764 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
765 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
766 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
769 " // transform unnormalized eye direction into tangent space\n"
771 " vec3 EyeVectorModelSpace;\n"
773 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
774 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
775 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
776 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
779 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
782 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
783 " VectorS = gl_MultiTexCoord1.xyz;\n"
784 " VectorT = gl_MultiTexCoord2.xyz;\n"
785 " VectorR = gl_MultiTexCoord3.xyz;\n"
788 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
789 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
790 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
791 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
794 "// transform vertex to camera space, using ftransform to match non-VS\n"
796 " gl_Position = ftransform();\n"
798 "#ifdef MODE_WATER\n"
799 " ModelViewProjectionPosition = gl_Position;\n"
801 "#ifdef MODE_REFRACTION\n"
802 " ModelViewProjectionPosition = gl_Position;\n"
804 "#ifdef USEREFLECTION\n"
805 " ModelViewProjectionPosition = gl_Position;\n"
809 "#endif // VERTEX_SHADER\n"
814 "// fragment shader specific:\n"
815 "#ifdef FRAGMENT_SHADER\n"
817 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
818 "uniform sampler2D Texture_Normal;\n"
819 "uniform sampler2D Texture_Color;\n"
820 "uniform sampler2D Texture_Gloss;\n"
821 "uniform sampler2D Texture_Glow;\n"
822 "uniform sampler2D Texture_SecondaryNormal;\n"
823 "uniform sampler2D Texture_SecondaryColor;\n"
824 "uniform sampler2D Texture_SecondaryGloss;\n"
825 "uniform sampler2D Texture_SecondaryGlow;\n"
826 "uniform sampler2D Texture_Pants;\n"
827 "uniform sampler2D Texture_Shirt;\n"
828 "uniform sampler2D Texture_FogMask;\n"
829 "uniform sampler2D Texture_Lightmap;\n"
830 "uniform sampler2D Texture_Deluxemap;\n"
831 "uniform sampler2D Texture_Refraction;\n"
832 "uniform sampler2D Texture_Reflection;\n"
833 "uniform sampler2D Texture_Attenuation;\n"
834 "uniform samplerCube Texture_Cube;\n"
836 "#define showshadowmap 0\n"
838 "#ifdef USESHADOWMAPRECT\n"
839 "# ifdef USESHADOWSAMPLER\n"
840 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
842 "uniform sampler2DRect Texture_ShadowMapRect;\n"
846 "#ifdef USESHADOWMAP2D\n"
847 "# ifdef USESHADOWSAMPLER\n"
848 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
850 "uniform sampler2D Texture_ShadowMap2D;\n"
854 "#ifdef USESHADOWMAPVSDCT\n"
855 "uniform samplerCube Texture_CubeProjection;\n"
858 "#ifdef USESHADOWMAPCUBE\n"
859 "# ifdef USESHADOWSAMPLER\n"
860 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
862 "uniform samplerCube Texture_ShadowMapCube;\n"
866 "uniform myhalf3 LightColor;\n"
867 "uniform myhalf3 AmbientColor;\n"
868 "uniform myhalf3 DiffuseColor;\n"
869 "uniform myhalf3 SpecularColor;\n"
870 "uniform myhalf3 Color_Pants;\n"
871 "uniform myhalf3 Color_Shirt;\n"
872 "uniform myhalf3 FogColor;\n"
874 "uniform myhalf4 TintColor;\n"
877 "//#ifdef MODE_WATER\n"
878 "uniform vec4 DistortScaleRefractReflect;\n"
879 "uniform vec4 ScreenScaleRefractReflect;\n"
880 "uniform vec4 ScreenCenterRefractReflect;\n"
881 "uniform myhalf4 RefractColor;\n"
882 "uniform myhalf4 ReflectColor;\n"
883 "uniform myhalf ReflectFactor;\n"
884 "uniform myhalf ReflectOffset;\n"
886 "//# ifdef MODE_REFRACTION\n"
887 "//uniform vec4 DistortScaleRefractReflect;\n"
888 "//uniform vec4 ScreenScaleRefractReflect;\n"
889 "//uniform vec4 ScreenCenterRefractReflect;\n"
890 "//uniform myhalf4 RefractColor;\n"
891 "//# ifdef USEREFLECTION\n"
892 "//uniform myhalf4 ReflectColor;\n"
895 "//# ifdef USEREFLECTION\n"
896 "//uniform vec4 DistortScaleRefractReflect;\n"
897 "//uniform vec4 ScreenScaleRefractReflect;\n"
898 "//uniform vec4 ScreenCenterRefractReflect;\n"
899 "//uniform myhalf4 ReflectColor;\n"
904 "uniform myhalf3 GlowColor;\n"
905 "uniform myhalf SceneBrightness;\n"
907 "uniform float OffsetMapping_Scale;\n"
908 "uniform float OffsetMapping_Bias;\n"
909 "uniform float FogRangeRecip;\n"
910 "uniform float FogPlaneViewDist;\n"
911 "uniform float FogHeightFade;\n"
913 "uniform myhalf AmbientScale;\n"
914 "uniform myhalf DiffuseScale;\n"
915 "uniform myhalf SpecularScale;\n"
916 "uniform myhalf SpecularPower;\n"
918 "#ifdef USEOFFSETMAPPING\n"
919 "vec2 OffsetMapping(vec2 TexCoord)\n"
921 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
922 " // 14 sample relief mapping: linear search and then binary search\n"
923 " // this basically steps forward a small amount repeatedly until it finds\n"
924 " // itself inside solid, then jitters forward and back using decreasing\n"
925 " // amounts to find the impact\n"
926 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
927 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
928 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
929 " vec3 RT = vec3(TexCoord, 1);\n"
930 " OffsetVector *= 0.1;\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);\n"
936 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
937 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
938 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
939 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
940 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
941 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
942 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
943 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
944 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
947 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
948 " // this basically moves forward the full distance, and then backs up based\n"
949 " // on height of samples\n"
950 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
951 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
952 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
953 " TexCoord += OffsetVector;\n"
954 " OffsetVector *= 0.333;\n"
955 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
956 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
957 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
958 " return TexCoord;\n"
961 "#endif // USEOFFSETMAPPING\n"
963 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
964 "uniform vec2 ShadowMap_TextureScale;\n"
965 "uniform vec4 ShadowMap_Parameters;\n"
968 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
969 "vec3 GetShadowMapTC2D(vec3 dir)\n"
971 " vec3 adir = abs(dir);\n"
972 "# ifndef USESHADOWMAPVSDCT\n"
976 " if (adir.x > adir.y)\n"
978 " if (adir.x > adir.z) // X\n"
982 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
988 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
993 " if (adir.y > adir.z) // Y\n"
997 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1003 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1007 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1008 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1009 " stc.z += ShadowMap_Parameters.z;\n"
1010 "# if showshadowmap\n"
1011 " stc.xy *= ShadowMap_TextureScale;\n"
1015 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1016 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1017 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1018 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1019 " stc.z += ShadowMap_Parameters.z;\n"
1020 "# if showshadowmap\n"
1021 " stc.xy *= ShadowMap_TextureScale;\n"
1026 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1028 "#ifdef USESHADOWMAPCUBE\n"
1029 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1031 " vec3 adir = abs(dir);\n"
1032 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1036 "#if !showshadowmap\n"
1037 "# ifdef USESHADOWMAPRECT\n"
1038 "float ShadowMapCompare(vec3 dir)\n"
1040 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1042 "# ifdef USESHADOWSAMPLER\n"
1044 "# ifdef USESHADOWMAPPCF\n"
1045 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1046 " 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"
1048 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1053 "# ifdef USESHADOWMAPPCF\n"
1054 "# if USESHADOWMAPPCF > 1\n"
1055 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1056 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1057 " 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"
1058 " 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"
1059 " 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"
1060 " 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"
1061 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1062 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1064 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1065 " vec2 offset = fract(shadowmaptc.xy);\n"
1066 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1067 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1068 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1069 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1070 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1073 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1081 "# ifdef USESHADOWMAP2D\n"
1082 "float ShadowMapCompare(vec3 dir)\n"
1084 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1087 "# ifdef USESHADOWSAMPLER\n"
1088 "# ifdef USESHADOWMAPPCF\n"
1089 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1090 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1091 " 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"
1093 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1096 "# ifdef USESHADOWMAPPCF\n"
1097 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1098 "# ifdef GL_ARB_texture_gather\n"
1099 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1101 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1103 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1104 " center *= ShadowMap_TextureScale;\n"
1105 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1106 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1107 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1108 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1109 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1110 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1111 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1113 "# ifdef GL_EXT_gpu_shader4\n"
1114 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1116 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1118 "# if USESHADOWMAPPCF > 1\n"
1119 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1120 " center *= ShadowMap_TextureScale;\n"
1121 " 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"
1122 " 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"
1123 " 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"
1124 " 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"
1125 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1126 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1128 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1129 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1130 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1131 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1132 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1133 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1137 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1144 "# ifdef USESHADOWMAPCUBE\n"
1145 "float ShadowMapCompare(vec3 dir)\n"
1147 " // apply depth texture cubemap as light filter\n"
1148 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1150 "# ifdef USESHADOWSAMPLER\n"
1151 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1153 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1160 "#ifdef MODE_WATER\n"
1165 "#ifdef USEOFFSETMAPPING\n"
1166 " // apply offsetmapping\n"
1167 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1168 "#define TexCoord TexCoordOffset\n"
1171 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1172 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1173 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1174 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1175 " // FIXME temporary hack to detect the case that the reflection\n"
1176 " // gets blackened at edges due to leaving the area that contains actual\n"
1178 " // Remove this 'ack once we have a better way to stop this thing from\n"
1180 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1181 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1182 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1183 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1184 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1185 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1186 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1187 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1188 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1189 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1190 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1191 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1194 "#else // !MODE_WATER\n"
1195 "#ifdef MODE_REFRACTION\n"
1197 "// refraction pass\n"
1200 "#ifdef USEOFFSETMAPPING\n"
1201 " // apply offsetmapping\n"
1202 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1203 "#define TexCoord TexCoordOffset\n"
1206 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1207 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1208 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1209 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1210 " // FIXME temporary hack to detect the case that the reflection\n"
1211 " // gets blackened at edges due to leaving the area that contains actual\n"
1213 " // Remove this 'ack once we have a better way to stop this thing from\n"
1215 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1216 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1217 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1218 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1219 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1220 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1223 "#else // !MODE_REFRACTION\n"
1226 "#ifdef USEOFFSETMAPPING\n"
1227 " // apply offsetmapping\n"
1228 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1229 "#define TexCoord TexCoordOffset\n"
1232 " // combine the diffuse textures (base, pants, shirt)\n"
1233 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1234 "#ifdef USECOLORMAPPING\n"
1235 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1237 "#ifdef USEVERTEXTEXTUREBLEND\n"
1238 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1239 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1240 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1241 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1243 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1246 "#ifdef USEDIFFUSE\n"
1247 " // get the surface normal and the gloss color\n"
1248 "# ifdef USEVERTEXTEXTUREBLEND\n"
1249 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1250 "# ifdef USESPECULAR\n"
1251 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1254 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1255 "# ifdef USESPECULAR\n"
1256 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1263 "#ifdef MODE_LIGHTSOURCE\n"
1264 " // light source\n"
1266 " // calculate surface normal, light normal, and specular normal\n"
1267 " // compute color intensity for the two textures (colormap and glossmap)\n"
1268 " // scale by light color and attenuation as efficiently as possible\n"
1269 " // (do as much scalar math as possible rather than vector math)\n"
1270 "# ifdef USEDIFFUSE\n"
1271 " // get the light normal\n"
1272 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1274 "# ifdef USESPECULAR\n"
1275 "# ifndef USEEXACTSPECULARMATH\n"
1276 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1279 " // calculate directional shading\n"
1280 "# ifdef USEEXACTSPECULARMATH\n"
1281 " 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"
1283 " 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"
1286 "# ifdef USEDIFFUSE\n"
1287 " // calculate directional shading\n"
1288 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1290 " // calculate directionless shading\n"
1291 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1295 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1296 "#if !showshadowmap\n"
1297 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1301 "# ifdef USECUBEFILTER\n"
1302 " // apply light cubemap filter\n"
1303 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1304 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1306 "#endif // MODE_LIGHTSOURCE\n"
1311 "#ifdef MODE_LIGHTDIRECTION\n"
1312 " // directional model lighting\n"
1313 "# ifdef USEDIFFUSE\n"
1314 " // get the light normal\n"
1315 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1317 "# ifdef USESPECULAR\n"
1318 " // calculate directional shading\n"
1319 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1320 "# ifdef USEEXACTSPECULARMATH\n"
1321 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1323 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1324 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1327 "# ifdef USEDIFFUSE\n"
1329 " // calculate directional shading\n"
1330 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1332 " color.rgb *= AmbientColor;\n"
1335 "#endif // MODE_LIGHTDIRECTION\n"
1340 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1341 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1343 " // get the light normal\n"
1344 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1345 " myhalf3 diffusenormal;\n"
1346 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1347 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1348 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1349 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1350 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1351 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1352 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1353 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1354 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1355 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1356 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1357 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1358 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1359 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1360 "# ifdef USESPECULAR\n"
1361 "# ifdef USEEXACTSPECULARMATH\n"
1362 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1364 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1365 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1369 " // apply lightmap color\n"
1370 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1371 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1376 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1377 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1379 " // get the light normal\n"
1380 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1381 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1382 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1383 "# ifdef USESPECULAR\n"
1384 "# ifdef USEEXACTSPECULARMATH\n"
1385 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1387 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1388 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1392 " // apply lightmap color\n"
1393 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1394 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1399 "#ifdef MODE_LIGHTMAP\n"
1400 " // apply lightmap color\n"
1401 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1402 "#endif // MODE_LIGHTMAP\n"
1407 "#ifdef MODE_VERTEXCOLOR\n"
1408 " // apply lightmap color\n"
1409 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1410 "#endif // MODE_VERTEXCOLOR\n"
1415 "#ifdef MODE_FLATCOLOR\n"
1416 "#endif // MODE_FLATCOLOR\n"
1424 " color *= TintColor;\n"
1427 "#ifdef USEVERTEXTEXTUREBLEND\n"
1428 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1430 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1434 " color.rgb *= SceneBrightness;\n"
1436 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1439 "#ifdef USEFOGOUTSIDE\n"
1440 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1442 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1444 "// float FogHeightFade1 = -0.5/1024.0;\n"
1445 "// if (FogPlaneViewDist >= 0.0)\n"
1446 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade1);\n"
1448 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade1);\n"
1449 "//# ifdef USEFOGABOVE\n"
1450 "// if (FogPlaneViewDist >= 0.0)\n"
1451 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist);\n"
1453 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist));\n"
1454 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1455 "// fogfrac *= min(1.0, (max(0.0, fade*FogPlaneVertexDist) + max(0.0, fade*FogPlaneViewDist)));\n"
1456 "// fogfrac *= min(1.0, (max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1457 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1459 " //fogfrac *= min(1.0, max(0.0, (max(-2048, min(0, FogPlaneVertexDist)) + max(-2048, min(0, FogPlaneViewDist)))/-2048.0));\n"
1460 " //float fade = -0.5/128.0;\n"
1461 " //fogfrac *= max(0.0, min(1.0, fade*FogPlaneVertexDist)) + max(0.0, min(1.0, fade*FogPlaneViewDist));\n"
1462 " //fogfrac *= max(0.0, min(1.0, FogHeightFade1*FogPlaneVertexDist)) + max(0.0, min(1.0, FogHeightFade1*FogPlaneViewDist));\n"
1463 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1464 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1465 " //fogfrac *= min(1.0, min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1466 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1467 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1468 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1470 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0))));\n"
1473 " // 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"
1474 "#ifdef USEREFLECTION\n"
1475 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1476 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1477 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1478 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1479 " // FIXME temporary hack to detect the case that the reflection\n"
1480 " // gets blackened at edges due to leaving the area that contains actual\n"
1482 " // Remove this 'ack once we have a better way to stop this thing from\n"
1484 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1485 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1486 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1487 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1488 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1489 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1492 " gl_FragColor = vec4(color);\n"
1494 "#if showshadowmap\n"
1495 "# ifdef USESHADOWMAPRECT\n"
1496 "# ifdef USESHADOWSAMPLER\n"
1497 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1499 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1502 "# ifdef USESHADOWMAP2D\n"
1503 "# ifdef USESHADOWSAMPLER\n"
1504 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1506 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1510 "# ifdef USESHADOWMAPCUBE\n"
1511 "# ifdef USESHADOWSAMPLER\n"
1512 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1514 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1519 "#endif // !MODE_REFRACTION\n"
1520 "#endif // !MODE_WATER\n"
1522 "#endif // FRAGMENT_SHADER\n"
1524 "#endif // !MODE_BLOOMBLUR\n"
1525 "#endif // !MODE_GENERIC\n"
1526 "#endif // !MODE_POSTPROCESS\n"
1527 "#endif // !MODE_SHOWDEPTH\n"
1528 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1531 typedef struct shaderpermutationinfo_s
1533 const char *pretext;
1536 shaderpermutationinfo_t;
1538 typedef struct shadermodeinfo_s
1540 const char *vertexfilename;
1541 const char *geometryfilename;
1542 const char *fragmentfilename;
1543 const char *pretext;
1548 typedef enum shaderpermutation_e
1550 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1551 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1552 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1553 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1554 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1555 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1556 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1557 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1558 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1559 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1560 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1561 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1562 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1563 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1564 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1565 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1566 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1567 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1568 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1569 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1570 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1571 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1572 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1573 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1574 SHADERPERMUTATION_LIMIT = 1<<24, ///< size of permutations array
1575 SHADERPERMUTATION_COUNT = 24 ///< size of shaderpermutationinfo array
1577 shaderpermutation_t;
1579 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1580 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1582 {"#define USEDIFFUSE\n", " diffuse"},
1583 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1584 {"#define USEVIEWTINT\n", " viewtint"},
1585 {"#define USECOLORMAPPING\n", " colormapping"},
1586 {"#define USESATURATION\n", " saturation"},
1587 {"#define USEFOGINSIDE\n", " foginside"},
1588 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1589 {"#define USEGAMMARAMPS\n", " gammaramps"},
1590 {"#define USECUBEFILTER\n", " cubefilter"},
1591 {"#define USEGLOW\n", " glow"},
1592 {"#define USEBLOOM\n", " bloom"},
1593 {"#define USESPECULAR\n", " specular"},
1594 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1595 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1596 {"#define USEREFLECTION\n", " reflection"},
1597 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1598 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1599 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1600 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1601 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1602 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1603 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1604 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1605 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1608 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1609 typedef enum shadermode_e
1611 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1612 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1613 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1614 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1615 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1616 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1617 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1618 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1619 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1620 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1621 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1622 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1623 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1628 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1629 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1631 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1632 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1633 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1634 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1635 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1636 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1637 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1638 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1639 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1640 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1641 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1642 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1643 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1646 struct r_glsl_permutation_s;
1647 typedef struct r_glsl_permutation_s
1649 /// hash lookup data
1650 struct r_glsl_permutation_s *hashnext;
1652 unsigned int permutation;
1654 /// indicates if we have tried compiling this permutation already
1656 /// 0 if compilation failed
1658 /// locations of detected uniforms in program object, or -1 if not found
1659 int loc_Texture_First;
1660 int loc_Texture_Second;
1661 int loc_Texture_GammaRamps;
1662 int loc_Texture_Normal;
1663 int loc_Texture_Color;
1664 int loc_Texture_Gloss;
1665 int loc_Texture_Glow;
1666 int loc_Texture_SecondaryNormal;
1667 int loc_Texture_SecondaryColor;
1668 int loc_Texture_SecondaryGloss;
1669 int loc_Texture_SecondaryGlow;
1670 int loc_Texture_Pants;
1671 int loc_Texture_Shirt;
1672 int loc_Texture_FogMask;
1673 int loc_Texture_Lightmap;
1674 int loc_Texture_Deluxemap;
1675 int loc_Texture_Attenuation;
1676 int loc_Texture_Cube;
1677 int loc_Texture_Refraction;
1678 int loc_Texture_Reflection;
1679 int loc_Texture_ShadowMapRect;
1680 int loc_Texture_ShadowMapCube;
1681 int loc_Texture_ShadowMap2D;
1682 int loc_Texture_CubeProjection;
1684 int loc_LightPosition;
1685 int loc_EyePosition;
1686 int loc_Color_Pants;
1687 int loc_Color_Shirt;
1689 int loc_FogPlaneViewDist;
1690 int loc_FogRangeRecip;
1691 int loc_FogHeightFade;
1692 int loc_AmbientScale;
1693 int loc_DiffuseScale;
1694 int loc_SpecularScale;
1695 int loc_SpecularPower;
1697 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1698 int loc_OffsetMapping_Scale;
1700 int loc_AmbientColor;
1701 int loc_DiffuseColor;
1702 int loc_SpecularColor;
1704 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1705 int loc_GammaCoeff; ///< 1 / gamma
1706 int loc_DistortScaleRefractReflect;
1707 int loc_ScreenScaleRefractReflect;
1708 int loc_ScreenCenterRefractReflect;
1709 int loc_RefractColor;
1710 int loc_ReflectColor;
1711 int loc_ReflectFactor;
1712 int loc_ReflectOffset;
1720 int loc_ShadowMap_TextureScale;
1721 int loc_ShadowMap_Parameters;
1723 r_glsl_permutation_t;
1725 #define SHADERPERMUTATION_HASHSIZE 256
1727 /// information about each possible shader permutation
1728 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1729 /// currently selected permutation
1730 r_glsl_permutation_t *r_glsl_permutation;
1731 /// storage for permutations linked in the hash table
1732 memexpandablearray_t r_glsl_permutationarray;
1734 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1736 //unsigned int hashdepth = 0;
1737 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1738 r_glsl_permutation_t *p;
1739 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1741 if (p->mode == mode && p->permutation == permutation)
1743 //if (hashdepth > 10)
1744 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1749 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1751 p->permutation = permutation;
1752 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1753 r_glsl_permutationhash[mode][hashindex] = p;
1754 //if (hashdepth > 10)
1755 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1759 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1762 if (!filename || !filename[0])
1764 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1767 if (printfromdisknotice)
1768 Con_DPrint("from disk... ");
1769 return shaderstring;
1771 else if (!strcmp(filename, "glsl/default.glsl"))
1773 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1774 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1776 return shaderstring;
1779 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1782 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1783 int vertstrings_count = 0;
1784 int geomstrings_count = 0;
1785 int fragstrings_count = 0;
1786 char *vertexstring, *geometrystring, *fragmentstring;
1787 const char *vertstrings_list[32+3];
1788 const char *geomstrings_list[32+3];
1789 const char *fragstrings_list[32+3];
1790 char permutationname[256];
1797 permutationname[0] = 0;
1798 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1799 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1800 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1802 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1804 // the first pretext is which type of shader to compile as
1805 // (later these will all be bound together as a program object)
1806 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1807 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1808 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1810 // the second pretext is the mode (for example a light source)
1811 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1812 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1813 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1814 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1816 // now add all the permutation pretexts
1817 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1819 if (permutation & (1<<i))
1821 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1822 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1823 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1824 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1828 // keep line numbers correct
1829 vertstrings_list[vertstrings_count++] = "\n";
1830 geomstrings_list[geomstrings_count++] = "\n";
1831 fragstrings_list[fragstrings_count++] = "\n";
1835 // now append the shader text itself
1836 vertstrings_list[vertstrings_count++] = vertexstring;
1837 geomstrings_list[geomstrings_count++] = geometrystring;
1838 fragstrings_list[fragstrings_count++] = fragmentstring;
1840 // if any sources were NULL, clear the respective list
1842 vertstrings_count = 0;
1843 if (!geometrystring)
1844 geomstrings_count = 0;
1845 if (!fragmentstring)
1846 fragstrings_count = 0;
1848 // compile the shader program
1849 if (vertstrings_count + geomstrings_count + fragstrings_count)
1850 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1854 qglUseProgramObjectARB(p->program);CHECKGLERROR
1855 // look up all the uniform variable names we care about, so we don't
1856 // have to look them up every time we set them
1857 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1858 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1859 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1860 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1861 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1862 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1863 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1864 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1865 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1866 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1867 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1868 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1869 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1870 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1871 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1872 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1873 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1874 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1875 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1876 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1877 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1878 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1879 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1880 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1881 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1882 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1883 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1884 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1885 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1886 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
1887 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
1888 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1889 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
1890 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1891 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1892 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1893 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1894 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1895 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1896 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1897 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1898 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1899 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1900 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1901 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1902 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1903 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1904 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1905 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1906 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1907 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1908 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1909 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1910 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1911 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1912 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1913 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1914 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1915 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1916 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1917 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1918 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1919 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1920 // initialize the samplers to refer to the texture units we use
1921 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1922 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1923 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1924 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1925 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1926 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1927 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1928 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1929 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1930 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1931 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1932 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1933 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1934 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1935 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1936 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1937 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1938 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1939 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1940 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1941 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1942 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1943 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1944 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1946 if (developer.integer)
1947 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1950 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1954 Mem_Free(vertexstring);
1956 Mem_Free(geometrystring);
1958 Mem_Free(fragmentstring);
1961 void R_GLSL_Restart_f(void)
1963 unsigned int i, limit;
1964 r_glsl_permutation_t *p;
1965 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1966 for (i = 0;i < limit;i++)
1968 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1970 GL_Backend_FreeProgram(p->program);
1971 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1974 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1977 void R_GLSL_DumpShader_f(void)
1981 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1984 Con_Printf("failed to write to glsl/default.glsl\n");
1988 FS_Print(file, "/* The engine may define the following macros:\n");
1989 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1990 for (i = 0;i < SHADERMODE_COUNT;i++)
1991 FS_Print(file, shadermodeinfo[i].pretext);
1992 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1993 FS_Print(file, shaderpermutationinfo[i].pretext);
1994 FS_Print(file, "*/\n");
1995 FS_Print(file, builtinshaderstring);
1998 Con_Printf("glsl/default.glsl written\n");
2001 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
2003 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2004 if (r_glsl_permutation != perm)
2006 r_glsl_permutation = perm;
2007 if (!r_glsl_permutation->program)
2009 if (!r_glsl_permutation->compiled)
2010 R_GLSL_CompilePermutation(perm, mode, permutation);
2011 if (!r_glsl_permutation->program)
2013 // remove features until we find a valid permutation
2015 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2017 // reduce i more quickly whenever it would not remove any bits
2018 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2019 if (!(permutation & j))
2022 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2023 if (!r_glsl_permutation->compiled)
2024 R_GLSL_CompilePermutation(perm, mode, permutation);
2025 if (r_glsl_permutation->program)
2028 if (i >= SHADERPERMUTATION_COUNT)
2030 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");
2031 Cvar_SetValueQuick(&r_glsl, 0);
2032 R_GLSL_Restart_f(); // unload shaders
2033 return; // no bit left to clear
2038 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2042 void R_SetupGenericShader(qboolean usetexture)
2044 if (vid.support.arb_fragment_shader)
2046 if (r_glsl.integer && r_glsl_usegeneric.integer)
2047 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2048 else if (r_glsl_permutation)
2050 r_glsl_permutation = NULL;
2051 qglUseProgramObjectARB(0);CHECKGLERROR
2056 void R_SetupGenericTwoTextureShader(int texturemode)
2058 if (vid.support.arb_fragment_shader)
2060 if (r_glsl.integer && r_glsl_usegeneric.integer)
2061 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))));
2062 else if (r_glsl_permutation)
2064 r_glsl_permutation = NULL;
2065 qglUseProgramObjectARB(0);CHECKGLERROR
2068 if (!r_glsl_permutation)
2070 if (texturemode == GL_DECAL && gl_combine.integer)
2071 texturemode = GL_INTERPOLATE_ARB;
2072 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
2076 void R_SetupDepthOrShadowShader(void)
2078 if (vid.support.arb_fragment_shader)
2080 if (r_glsl.integer && r_glsl_usegeneric.integer)
2081 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2082 else if (r_glsl_permutation)
2084 r_glsl_permutation = NULL;
2085 qglUseProgramObjectARB(0);CHECKGLERROR
2090 void R_SetupShowDepthShader(void)
2092 if (vid.support.arb_fragment_shader)
2094 if (r_glsl.integer && r_glsl_usegeneric.integer)
2095 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2096 else if (r_glsl_permutation)
2098 r_glsl_permutation = NULL;
2099 qglUseProgramObjectARB(0);CHECKGLERROR
2104 extern rtexture_t *r_shadow_attenuationgradienttexture;
2105 extern rtexture_t *r_shadow_attenuation2dtexture;
2106 extern rtexture_t *r_shadow_attenuation3dtexture;
2107 extern qboolean r_shadow_usingshadowmaprect;
2108 extern qboolean r_shadow_usingshadowmapcube;
2109 extern qboolean r_shadow_usingshadowmap2d;
2110 extern float r_shadow_shadowmap_texturescale[2];
2111 extern float r_shadow_shadowmap_parameters[4];
2112 extern qboolean r_shadow_shadowmapvsdct;
2113 extern qboolean r_shadow_shadowmapsampler;
2114 extern int r_shadow_shadowmappcf;
2115 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2117 // select a permutation of the lighting shader appropriate to this
2118 // combination of texture, entity, light source, and fogging, only use the
2119 // minimum features necessary to avoid wasting rendering time in the
2120 // fragment shader on features that are not being used
2121 unsigned int permutation = 0;
2122 unsigned int mode = 0;
2123 // TODO: implement geometry-shader based shadow volumes someday
2124 if (r_glsl_offsetmapping.integer)
2126 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2127 if (r_glsl_offsetmapping_reliefmapping.integer)
2128 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2130 if (rsurfacepass == RSURFPASS_BACKGROUND)
2132 // distorted background
2133 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2134 mode = SHADERMODE_WATER;
2136 mode = SHADERMODE_REFRACTION;
2138 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2141 mode = SHADERMODE_LIGHTSOURCE;
2142 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2143 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2144 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2145 permutation |= SHADERPERMUTATION_CUBEFILTER;
2146 if (diffusescale > 0)
2147 permutation |= SHADERPERMUTATION_DIFFUSE;
2148 if (specularscale > 0)
2149 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2150 if (r_refdef.fogenabled)
2151 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2152 if (rsurface.texture->colormapping)
2153 permutation |= SHADERPERMUTATION_COLORMAPPING;
2154 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2156 if (r_shadow_usingshadowmaprect)
2157 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2158 if (r_shadow_usingshadowmap2d)
2159 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2160 if (r_shadow_usingshadowmapcube)
2161 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2162 else if(r_shadow_shadowmapvsdct)
2163 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2165 if (r_shadow_shadowmapsampler)
2166 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2167 if (r_shadow_shadowmappcf > 1)
2168 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2169 else if (r_shadow_shadowmappcf)
2170 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2173 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2175 // unshaded geometry (fullbright or ambient model lighting)
2176 mode = SHADERMODE_FLATCOLOR;
2177 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2178 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2179 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2180 permutation |= SHADERPERMUTATION_GLOW;
2181 if (r_refdef.fogenabled)
2182 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2183 if (rsurface.texture->colormapping)
2184 permutation |= SHADERPERMUTATION_COLORMAPPING;
2185 if (r_glsl_offsetmapping.integer)
2187 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2188 if (r_glsl_offsetmapping_reliefmapping.integer)
2189 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2191 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2192 permutation |= SHADERPERMUTATION_REFLECTION;
2194 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2196 // directional model lighting
2197 mode = SHADERMODE_LIGHTDIRECTION;
2198 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2199 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2200 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2201 permutation |= SHADERPERMUTATION_GLOW;
2202 permutation |= SHADERPERMUTATION_DIFFUSE;
2203 if (specularscale > 0)
2204 permutation |= SHADERPERMUTATION_SPECULAR;
2205 if (r_refdef.fogenabled)
2206 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2207 if (rsurface.texture->colormapping)
2208 permutation |= SHADERPERMUTATION_COLORMAPPING;
2209 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2210 permutation |= SHADERPERMUTATION_REFLECTION;
2212 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2214 // ambient model lighting
2215 mode = SHADERMODE_LIGHTDIRECTION;
2216 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2217 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2218 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2219 permutation |= SHADERPERMUTATION_GLOW;
2220 if (r_refdef.fogenabled)
2221 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2222 if (rsurface.texture->colormapping)
2223 permutation |= SHADERPERMUTATION_COLORMAPPING;
2224 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2225 permutation |= SHADERPERMUTATION_REFLECTION;
2230 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2232 // deluxemapping (light direction texture)
2233 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2234 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2236 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2237 permutation |= SHADERPERMUTATION_DIFFUSE;
2238 if (specularscale > 0)
2239 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2241 else if (r_glsl_deluxemapping.integer >= 2)
2243 // fake deluxemapping (uniform light direction in tangentspace)
2244 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2245 permutation |= SHADERPERMUTATION_DIFFUSE;
2246 if (specularscale > 0)
2247 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2249 else if (rsurface.uselightmaptexture)
2251 // ordinary lightmapping (q1bsp, q3bsp)
2252 mode = SHADERMODE_LIGHTMAP;
2256 // ordinary vertex coloring (q3bsp)
2257 mode = SHADERMODE_VERTEXCOLOR;
2259 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2260 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2261 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2262 permutation |= SHADERPERMUTATION_GLOW;
2263 if (r_refdef.fogenabled)
2264 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2265 if (rsurface.texture->colormapping)
2266 permutation |= SHADERPERMUTATION_COLORMAPPING;
2267 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2268 permutation |= SHADERPERMUTATION_REFLECTION;
2270 if(permutation & SHADERPERMUTATION_SPECULAR)
2271 if(r_shadow_glossexact.integer)
2272 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2273 R_SetupShader_SetPermutation(mode, permutation);
2274 if (mode == SHADERMODE_LIGHTSOURCE)
2276 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2277 if (permutation & SHADERPERMUTATION_DIFFUSE)
2279 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2280 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2281 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2282 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2286 // ambient only is simpler
2287 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]);
2288 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2289 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2290 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2292 // additive passes are only darkened by fog, not tinted
2293 if (r_glsl_permutation->loc_FogColor >= 0)
2294 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2295 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]);
2296 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]);
2300 if (mode == SHADERMODE_LIGHTDIRECTION)
2302 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);
2303 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);
2304 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);
2305 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]);
2309 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2310 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2311 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2313 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]);
2314 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);
2315 // additive passes are only darkened by fog, not tinted
2316 if (r_glsl_permutation->loc_FogColor >= 0)
2318 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2319 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2321 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2323 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);
2324 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]);
2325 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]);
2326 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2327 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2328 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2329 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2331 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2332 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2333 if (r_glsl_permutation->loc_Color_Pants >= 0)
2335 if (rsurface.texture->currentskinframe->pants)
2336 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2338 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2340 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2342 if (rsurface.texture->currentskinframe->shirt)
2343 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2345 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2347 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]);
2348 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2349 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2350 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2351 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2353 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2357 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2359 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2363 #define SKINFRAME_HASH 1024
2367 int loadsequence; // incremented each level change
2368 memexpandablearray_t array;
2369 skinframe_t *hash[SKINFRAME_HASH];
2372 r_skinframe_t r_skinframe;
2374 void R_SkinFrame_PrepareForPurge(void)
2376 r_skinframe.loadsequence++;
2377 // wrap it without hitting zero
2378 if (r_skinframe.loadsequence >= 200)
2379 r_skinframe.loadsequence = 1;
2382 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2386 // mark the skinframe as used for the purging code
2387 skinframe->loadsequence = r_skinframe.loadsequence;
2390 void R_SkinFrame_Purge(void)
2394 for (i = 0;i < SKINFRAME_HASH;i++)
2396 for (s = r_skinframe.hash[i];s;s = s->next)
2398 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2400 if (s->merged == s->base)
2402 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2403 R_PurgeTexture(s->stain );s->stain = NULL;
2404 R_PurgeTexture(s->merged);s->merged = NULL;
2405 R_PurgeTexture(s->base );s->base = NULL;
2406 R_PurgeTexture(s->pants );s->pants = NULL;
2407 R_PurgeTexture(s->shirt );s->shirt = NULL;
2408 R_PurgeTexture(s->nmap );s->nmap = NULL;
2409 R_PurgeTexture(s->gloss );s->gloss = NULL;
2410 R_PurgeTexture(s->glow );s->glow = NULL;
2411 R_PurgeTexture(s->fog );s->fog = NULL;
2412 s->loadsequence = 0;
2418 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2420 char basename[MAX_QPATH];
2422 Image_StripImageExtension(name, basename, sizeof(basename));
2424 if( last == NULL ) {
2426 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2427 item = r_skinframe.hash[hashindex];
2432 // linearly search through the hash bucket
2433 for( ; item ; item = item->next ) {
2434 if( !strcmp( item->basename, basename ) ) {
2441 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2445 char basename[MAX_QPATH];
2447 Image_StripImageExtension(name, basename, sizeof(basename));
2449 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2450 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2451 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2455 rtexture_t *dyntexture;
2456 // check whether its a dynamic texture
2457 dyntexture = CL_GetDynTexture( basename );
2458 if (!add && !dyntexture)
2460 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2461 memset(item, 0, sizeof(*item));
2462 strlcpy(item->basename, basename, sizeof(item->basename));
2463 item->base = dyntexture; // either NULL or dyntexture handle
2464 item->textureflags = textureflags;
2465 item->comparewidth = comparewidth;
2466 item->compareheight = compareheight;
2467 item->comparecrc = comparecrc;
2468 item->next = r_skinframe.hash[hashindex];
2469 r_skinframe.hash[hashindex] = item;
2471 else if( item->base == NULL )
2473 rtexture_t *dyntexture;
2474 // check whether its a dynamic texture
2475 // 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]
2476 dyntexture = CL_GetDynTexture( basename );
2477 item->base = dyntexture; // either NULL or dyntexture handle
2480 R_SkinFrame_MarkUsed(item);
2484 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2486 unsigned long long avgcolor[5], wsum; \
2494 for(pix = 0; pix < cnt; ++pix) \
2497 for(comp = 0; comp < 3; ++comp) \
2499 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2502 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2504 for(comp = 0; comp < 3; ++comp) \
2505 avgcolor[comp] += getpixel * w; \
2508 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2509 avgcolor[4] += getpixel; \
2511 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2513 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2514 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2515 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2516 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2519 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2522 unsigned char *pixels;
2523 unsigned char *bumppixels;
2524 unsigned char *basepixels = NULL;
2525 int basepixels_width;
2526 int basepixels_height;
2527 skinframe_t *skinframe;
2529 if (cls.state == ca_dedicated)
2532 // return an existing skinframe if already loaded
2533 // if loading of the first image fails, don't make a new skinframe as it
2534 // would cause all future lookups of this to be missing
2535 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2536 if (skinframe && skinframe->base)
2539 basepixels = loadimagepixelsbgra(name, complain, true);
2540 if (basepixels == NULL)
2543 if (developer_loading.integer)
2544 Con_Printf("loading skin \"%s\"\n", name);
2546 // we've got some pixels to store, so really allocate this new texture now
2548 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2549 skinframe->stain = NULL;
2550 skinframe->merged = NULL;
2551 skinframe->base = r_texture_notexture;
2552 skinframe->pants = NULL;
2553 skinframe->shirt = NULL;
2554 skinframe->nmap = r_texture_blanknormalmap;
2555 skinframe->gloss = NULL;
2556 skinframe->glow = NULL;
2557 skinframe->fog = NULL;
2558 skinframe->hasalpha = false;
2560 basepixels_width = image_width;
2561 basepixels_height = image_height;
2562 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);
2564 if (textureflags & TEXF_ALPHA)
2566 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2568 if (basepixels[j] < 255)
2570 skinframe->hasalpha = true;
2574 if (r_loadfog && skinframe->hasalpha)
2576 // has transparent pixels
2577 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2578 for (j = 0;j < image_width * image_height * 4;j += 4)
2583 pixels[j+3] = basepixels[j+3];
2585 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);
2590 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2591 //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]);
2593 // _norm is the name used by tenebrae and has been adopted as standard
2594 if (r_loadnormalmap)
2596 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2598 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);
2602 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2604 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2605 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2606 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);
2608 Mem_Free(bumppixels);
2610 else if (r_shadow_bumpscale_basetexture.value > 0)
2612 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2613 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2614 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);
2618 // _luma is supported for tenebrae compatibility
2619 // (I think it's a very stupid name, but oh well)
2620 // _glow is the preferred name
2621 if ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))) {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;}
2622 if (r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false))) {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;}
2623 if ((pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false))) {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;}
2624 if ((pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false))) {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;}
2627 Mem_Free(basepixels);
2632 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2633 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2636 unsigned char *temp1, *temp2;
2637 skinframe_t *skinframe;
2639 if (cls.state == ca_dedicated)
2642 // if already loaded just return it, otherwise make a new skinframe
2643 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2644 if (skinframe && skinframe->base)
2647 skinframe->stain = NULL;
2648 skinframe->merged = NULL;
2649 skinframe->base = r_texture_notexture;
2650 skinframe->pants = NULL;
2651 skinframe->shirt = NULL;
2652 skinframe->nmap = r_texture_blanknormalmap;
2653 skinframe->gloss = NULL;
2654 skinframe->glow = NULL;
2655 skinframe->fog = NULL;
2656 skinframe->hasalpha = false;
2658 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2662 if (developer_loading.integer)
2663 Con_Printf("loading 32bit skin \"%s\"\n", name);
2665 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2667 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2668 temp2 = temp1 + width * height * 4;
2669 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2670 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2673 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2674 if (textureflags & TEXF_ALPHA)
2676 for (i = 3;i < width * height * 4;i += 4)
2678 if (skindata[i] < 255)
2680 skinframe->hasalpha = true;
2684 if (r_loadfog && skinframe->hasalpha)
2686 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2687 memcpy(fogpixels, skindata, width * height * 4);
2688 for (i = 0;i < width * height * 4;i += 4)
2689 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2690 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2691 Mem_Free(fogpixels);
2695 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2696 //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]);
2701 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2705 skinframe_t *skinframe;
2707 if (cls.state == ca_dedicated)
2710 // if already loaded just return it, otherwise make a new skinframe
2711 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2712 if (skinframe && skinframe->base)
2715 skinframe->stain = NULL;
2716 skinframe->merged = NULL;
2717 skinframe->base = r_texture_notexture;
2718 skinframe->pants = NULL;
2719 skinframe->shirt = NULL;
2720 skinframe->nmap = r_texture_blanknormalmap;
2721 skinframe->gloss = NULL;
2722 skinframe->glow = NULL;
2723 skinframe->fog = NULL;
2724 skinframe->hasalpha = false;
2726 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2730 if (developer_loading.integer)
2731 Con_Printf("loading quake skin \"%s\"\n", name);
2733 // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
2734 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
2735 memcpy(skinframe->qpixels, skindata, width*height);
2736 skinframe->qwidth = width;
2737 skinframe->qheight = height;
2740 for (i = 0;i < width * height;i++)
2741 featuresmask |= palette_featureflags[skindata[i]];
2743 skinframe->hasalpha = false;
2744 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2745 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2746 skinframe->qgeneratemerged = true;
2747 skinframe->qgeneratebase = skinframe->qhascolormapping;
2748 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2750 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2751 //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]);
2756 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2760 unsigned char *skindata;
2762 if (!skinframe->qpixels)
2765 if (!skinframe->qhascolormapping)
2766 colormapped = false;
2770 if (!skinframe->qgeneratebase)
2775 if (!skinframe->qgeneratemerged)
2779 width = skinframe->qwidth;
2780 height = skinframe->qheight;
2781 skindata = skinframe->qpixels;
2783 if (skinframe->qgeneratenmap)
2785 unsigned char *temp1, *temp2;
2786 skinframe->qgeneratenmap = false;
2787 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2788 temp2 = temp1 + width * height * 4;
2789 // use either a custom palette or the quake palette
2790 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2791 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2792 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2796 if (skinframe->qgenerateglow)
2798 skinframe->qgenerateglow = false;
2799 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
2804 skinframe->qgeneratebase = false;
2805 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
2806 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
2807 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
2811 skinframe->qgeneratemerged = false;
2812 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
2815 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
2817 Mem_Free(skinframe->qpixels);
2818 skinframe->qpixels = NULL;
2822 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)
2825 skinframe_t *skinframe;
2827 if (cls.state == ca_dedicated)
2830 // if already loaded just return it, otherwise make a new skinframe
2831 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2832 if (skinframe && skinframe->base)
2835 skinframe->stain = NULL;
2836 skinframe->merged = NULL;
2837 skinframe->base = r_texture_notexture;
2838 skinframe->pants = NULL;
2839 skinframe->shirt = NULL;
2840 skinframe->nmap = r_texture_blanknormalmap;
2841 skinframe->gloss = NULL;
2842 skinframe->glow = NULL;
2843 skinframe->fog = NULL;
2844 skinframe->hasalpha = false;
2846 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2850 if (developer_loading.integer)
2851 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2853 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
2854 if (textureflags & TEXF_ALPHA)
2856 for (i = 0;i < width * height;i++)
2858 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
2860 skinframe->hasalpha = true;
2864 if (r_loadfog && skinframe->hasalpha)
2865 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
2868 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2869 //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]);
2874 skinframe_t *R_SkinFrame_LoadMissing(void)
2876 skinframe_t *skinframe;
2878 if (cls.state == ca_dedicated)
2881 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2882 skinframe->stain = NULL;
2883 skinframe->merged = NULL;
2884 skinframe->base = r_texture_notexture;
2885 skinframe->pants = NULL;
2886 skinframe->shirt = NULL;
2887 skinframe->nmap = r_texture_blanknormalmap;
2888 skinframe->gloss = NULL;
2889 skinframe->glow = NULL;
2890 skinframe->fog = NULL;
2891 skinframe->hasalpha = false;
2893 skinframe->avgcolor[0] = rand() / RAND_MAX;
2894 skinframe->avgcolor[1] = rand() / RAND_MAX;
2895 skinframe->avgcolor[2] = rand() / RAND_MAX;
2896 skinframe->avgcolor[3] = 1;
2901 void R_Main_FreeViewCache(void)
2903 if (r_refdef.viewcache.entityvisible)
2904 Mem_Free(r_refdef.viewcache.entityvisible);
2905 if (r_refdef.viewcache.world_pvsbits)
2906 Mem_Free(r_refdef.viewcache.world_pvsbits);
2907 if (r_refdef.viewcache.world_leafvisible)
2908 Mem_Free(r_refdef.viewcache.world_leafvisible);
2909 if (r_refdef.viewcache.world_surfacevisible)
2910 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2911 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2914 void R_Main_ResizeViewCache(void)
2916 int numentities = r_refdef.scene.numentities;
2917 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
2918 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
2919 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
2920 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
2921 if (r_refdef.viewcache.maxentities < numentities)
2923 r_refdef.viewcache.maxentities = numentities;
2924 if (r_refdef.viewcache.entityvisible)
2925 Mem_Free(r_refdef.viewcache.entityvisible);
2926 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
2928 if (r_refdef.viewcache.world_numclusters != numclusters)
2930 r_refdef.viewcache.world_numclusters = numclusters;
2931 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
2932 if (r_refdef.viewcache.world_pvsbits)
2933 Mem_Free(r_refdef.viewcache.world_pvsbits);
2934 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
2936 if (r_refdef.viewcache.world_numleafs != numleafs)
2938 r_refdef.viewcache.world_numleafs = numleafs;
2939 if (r_refdef.viewcache.world_leafvisible)
2940 Mem_Free(r_refdef.viewcache.world_leafvisible);
2941 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
2943 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
2945 r_refdef.viewcache.world_numsurfaces = numsurfaces;
2946 if (r_refdef.viewcache.world_surfacevisible)
2947 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2948 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
2952 void gl_main_start(void)
2954 r_loadnormalmap = r_loadgloss = vid.support.arb_texture_env_dot3 || vid.support.arb_fragment_shader;
2959 memset(r_queries, 0, sizeof(r_queries));
2961 r_qwskincache = NULL;
2962 r_qwskincache_size = 0;
2964 // set up r_skinframe loading system for textures
2965 memset(&r_skinframe, 0, sizeof(r_skinframe));
2966 r_skinframe.loadsequence = 1;
2967 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2969 r_main_texturepool = R_AllocTexturePool();
2970 R_BuildBlankTextures();
2972 if (vid.support.arb_texture_cube_map)
2975 R_BuildNormalizationCube();
2977 r_texture_fogattenuation = NULL;
2978 r_texture_gammaramps = NULL;
2979 //r_texture_fogintensity = NULL;
2980 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2981 memset(&r_waterstate, 0, sizeof(r_waterstate));
2982 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2983 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2984 memset(&r_svbsp, 0, sizeof (r_svbsp));
2986 r_refdef.fogmasktable_density = 0;
2989 extern rtexture_t *loadingscreentexture;
2990 void gl_main_shutdown(void)
2992 R_Main_FreeViewCache();
2995 qglDeleteQueriesARB(r_maxqueries, r_queries);
2999 memset(r_queries, 0, sizeof(r_queries));
3001 r_qwskincache = NULL;
3002 r_qwskincache_size = 0;
3004 // clear out the r_skinframe state
3005 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3006 memset(&r_skinframe, 0, sizeof(r_skinframe));
3009 Mem_Free(r_svbsp.nodes);
3010 memset(&r_svbsp, 0, sizeof (r_svbsp));
3011 R_FreeTexturePool(&r_main_texturepool);
3012 loadingscreentexture = NULL;
3013 r_texture_blanknormalmap = NULL;
3014 r_texture_white = NULL;
3015 r_texture_grey128 = NULL;
3016 r_texture_black = NULL;
3017 r_texture_whitecube = NULL;
3018 r_texture_normalizationcube = NULL;
3019 r_texture_fogattenuation = NULL;
3020 r_texture_gammaramps = NULL;
3021 //r_texture_fogintensity = NULL;
3022 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3023 memset(&r_waterstate, 0, sizeof(r_waterstate));
3027 extern void CL_ParseEntityLump(char *entitystring);
3028 void gl_main_newmap(void)
3030 // FIXME: move this code to client
3032 char *entities, entname[MAX_QPATH];
3034 Mem_Free(r_qwskincache);
3035 r_qwskincache = NULL;
3036 r_qwskincache_size = 0;
3039 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
3040 l = (int)strlen(entname) - 4;
3041 if (l >= 0 && !strcmp(entname + l, ".bsp"))
3043 memcpy(entname + l, ".ent", 5);
3044 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3046 CL_ParseEntityLump(entities);
3051 if (cl.worldmodel->brush.entities)
3052 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3054 R_Main_FreeViewCache();
3057 void GL_Main_Init(void)
3059 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3061 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3062 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3063 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3064 if (gamemode == GAME_NEHAHRA)
3066 Cvar_RegisterVariable (&gl_fogenable);
3067 Cvar_RegisterVariable (&gl_fogdensity);
3068 Cvar_RegisterVariable (&gl_fogred);
3069 Cvar_RegisterVariable (&gl_foggreen);
3070 Cvar_RegisterVariable (&gl_fogblue);
3071 Cvar_RegisterVariable (&gl_fogstart);
3072 Cvar_RegisterVariable (&gl_fogend);
3073 Cvar_RegisterVariable (&gl_skyclip);
3075 Cvar_RegisterVariable(&r_motionblur);
3076 Cvar_RegisterVariable(&r_motionblur_maxblur);
3077 Cvar_RegisterVariable(&r_motionblur_bmin);
3078 Cvar_RegisterVariable(&r_motionblur_vmin);
3079 Cvar_RegisterVariable(&r_motionblur_vmax);
3080 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3081 Cvar_RegisterVariable(&r_motionblur_randomize);
3082 Cvar_RegisterVariable(&r_damageblur);
3083 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3084 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3085 Cvar_RegisterVariable(&r_equalize_entities_by);
3086 Cvar_RegisterVariable(&r_equalize_entities_to);
3087 Cvar_RegisterVariable(&r_animcache);
3088 Cvar_RegisterVariable(&r_depthfirst);
3089 Cvar_RegisterVariable(&r_useinfinitefarclip);
3090 Cvar_RegisterVariable(&r_farclip_base);
3091 Cvar_RegisterVariable(&r_farclip_world);
3092 Cvar_RegisterVariable(&r_nearclip);
3093 Cvar_RegisterVariable(&r_showbboxes);
3094 Cvar_RegisterVariable(&r_showsurfaces);
3095 Cvar_RegisterVariable(&r_showtris);
3096 Cvar_RegisterVariable(&r_shownormals);
3097 Cvar_RegisterVariable(&r_showlighting);
3098 Cvar_RegisterVariable(&r_showshadowvolumes);
3099 Cvar_RegisterVariable(&r_showcollisionbrushes);
3100 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3101 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3102 Cvar_RegisterVariable(&r_showdisabledepthtest);
3103 Cvar_RegisterVariable(&r_drawportals);
3104 Cvar_RegisterVariable(&r_drawentities);
3105 Cvar_RegisterVariable(&r_cullentities_trace);
3106 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3107 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3108 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3109 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3110 Cvar_RegisterVariable(&r_drawviewmodel);
3111 Cvar_RegisterVariable(&r_speeds);
3112 Cvar_RegisterVariable(&r_fullbrights);
3113 Cvar_RegisterVariable(&r_wateralpha);
3114 Cvar_RegisterVariable(&r_dynamic);
3115 Cvar_RegisterVariable(&r_fullbright);
3116 Cvar_RegisterVariable(&r_shadows);
3117 Cvar_RegisterVariable(&r_shadows_darken);
3118 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3119 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3120 Cvar_RegisterVariable(&r_shadows_throwdistance);
3121 Cvar_RegisterVariable(&r_shadows_throwdirection);
3122 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3123 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3124 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3125 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3126 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3127 Cvar_RegisterVariable(&r_fog_exp2);
3128 Cvar_RegisterVariable(&r_drawfog);
3129 Cvar_RegisterVariable(&r_textureunits);
3130 Cvar_RegisterVariable(&r_glsl);
3131 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3132 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3133 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3134 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3135 Cvar_RegisterVariable(&r_glsl_postprocess);
3136 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3137 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3138 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3139 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3140 Cvar_RegisterVariable(&r_glsl_usegeneric);
3141 Cvar_RegisterVariable(&r_water);
3142 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3143 Cvar_RegisterVariable(&r_water_clippingplanebias);
3144 Cvar_RegisterVariable(&r_water_refractdistort);
3145 Cvar_RegisterVariable(&r_water_reflectdistort);
3146 Cvar_RegisterVariable(&r_lerpsprites);
3147 Cvar_RegisterVariable(&r_lerpmodels);
3148 Cvar_RegisterVariable(&r_lerplightstyles);
3149 Cvar_RegisterVariable(&r_waterscroll);
3150 Cvar_RegisterVariable(&r_bloom);
3151 Cvar_RegisterVariable(&r_bloom_colorscale);
3152 Cvar_RegisterVariable(&r_bloom_brighten);
3153 Cvar_RegisterVariable(&r_bloom_blur);
3154 Cvar_RegisterVariable(&r_bloom_resolution);
3155 Cvar_RegisterVariable(&r_bloom_colorexponent);
3156 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3157 Cvar_RegisterVariable(&r_hdr);
3158 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3159 Cvar_RegisterVariable(&r_hdr_glowintensity);
3160 Cvar_RegisterVariable(&r_hdr_range);
3161 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3162 Cvar_RegisterVariable(&developer_texturelogging);
3163 Cvar_RegisterVariable(&gl_lightmaps);
3164 Cvar_RegisterVariable(&r_test);
3165 Cvar_RegisterVariable(&r_batchmode);
3166 Cvar_RegisterVariable(&r_glsl_saturation);
3167 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3168 Cvar_SetValue("r_fullbrights", 0);
3169 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3171 Cvar_RegisterVariable(&r_track_sprites);
3172 Cvar_RegisterVariable(&r_track_sprites_flags);
3173 Cvar_RegisterVariable(&r_track_sprites_scalew);
3174 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3177 extern void R_Textures_Init(void);
3178 extern void GL_Draw_Init(void);
3179 extern void GL_Main_Init(void);
3180 extern void R_Shadow_Init(void);
3181 extern void R_Sky_Init(void);
3182 extern void GL_Surf_Init(void);
3183 extern void R_Particles_Init(void);
3184 extern void R_Explosion_Init(void);
3185 extern void gl_backend_init(void);
3186 extern void Sbar_Init(void);
3187 extern void R_LightningBeams_Init(void);
3188 extern void Mod_RenderInit(void);
3190 void Render_Init(void)
3202 R_LightningBeams_Init();
3211 extern char *ENGINE_EXTENSIONS;
3214 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3215 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3216 gl_version = (const char *)qglGetString(GL_VERSION);
3217 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3221 if (!gl_platformextensions)
3222 gl_platformextensions = "";
3224 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3225 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3226 Con_Printf("GL_VERSION: %s\n", gl_version);
3227 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3228 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3230 VID_CheckExtensions();
3232 // LordHavoc: report supported extensions
3233 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3235 // clear to black (loading plaque will be seen over this)
3237 qglClearColor(0,0,0,1);CHECKGLERROR
3238 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3241 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3245 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3247 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3250 p = r_refdef.view.frustum + i;
3255 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3259 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3263 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3267 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3271 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3275 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3279 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3283 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3291 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3295 for (i = 0;i < numplanes;i++)
3302 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3306 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3310 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3314 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3318 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3322 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3326 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3330 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3338 //==================================================================================
3340 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3343 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3344 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3345 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3348 typedef struct r_animcache_entity_s
3355 qboolean wantnormals;
3356 qboolean wanttangents;
3358 r_animcache_entity_t;
3360 typedef struct r_animcache_s
3362 r_animcache_entity_t entity[MAX_EDICTS];
3368 static r_animcache_t r_animcachestate;
3370 void R_AnimCache_Free(void)
3373 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3375 r_animcachestate.entity[idx].maxvertices = 0;
3376 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3377 r_animcachestate.entity[idx].vertex3f = NULL;
3378 r_animcachestate.entity[idx].normal3f = NULL;
3379 r_animcachestate.entity[idx].svector3f = NULL;
3380 r_animcachestate.entity[idx].tvector3f = NULL;
3382 r_animcachestate.currentindex = 0;
3383 r_animcachestate.maxindex = 0;
3386 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3390 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3392 if (cache->maxvertices >= numvertices)
3395 // Release existing memory
3396 if (cache->vertex3f)
3397 Mem_Free(cache->vertex3f);
3399 // Pad by 1024 verts
3400 cache->maxvertices = (numvertices + 1023) & ~1023;
3401 arraySize = cache->maxvertices * 3;
3403 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3404 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3405 r_animcachestate.entity[cacheIdx].vertex3f = base;
3406 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3407 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3408 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3410 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3413 void R_AnimCache_NewFrame(void)
3417 if (r_animcache.integer && r_drawentities.integer)
3418 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3419 else if (r_animcachestate.maxindex)
3422 r_animcachestate.currentindex = 0;
3424 for (i = 0;i < r_refdef.scene.numentities;i++)
3425 r_refdef.scene.entities[i]->animcacheindex = -1;
3428 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3430 dp_model_t *model = ent->model;
3431 r_animcache_entity_t *c;
3432 // see if it's already cached this frame
3433 if (ent->animcacheindex >= 0)
3435 // add normals/tangents if needed
3436 c = r_animcachestate.entity + ent->animcacheindex;
3438 wantnormals = false;
3439 if (c->wanttangents)
3440 wanttangents = false;
3441 if (wantnormals || wanttangents)
3442 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3446 // see if this ent is worth caching
3447 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3449 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3451 // assign it a cache entry and make sure the arrays are big enough
3452 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3453 ent->animcacheindex = r_animcachestate.currentindex++;
3454 c = r_animcachestate.entity + ent->animcacheindex;
3455 c->wantnormals = wantnormals;
3456 c->wanttangents = wanttangents;
3457 model->AnimateVertices(model, ent->frameblend, ent->skeleton, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3462 void R_AnimCache_CacheVisibleEntities(void)
3465 qboolean wantnormals;
3466 qboolean wanttangents;
3468 if (!r_animcachestate.maxindex)
3471 wantnormals = !r_showsurfaces.integer;
3472 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3474 // TODO: thread this?
3476 for (i = 0;i < r_refdef.scene.numentities;i++)
3478 if (!r_refdef.viewcache.entityvisible[i])
3480 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3484 //==================================================================================
3486 static void R_View_UpdateEntityLighting (void)
3489 entity_render_t *ent;
3490 vec3_t tempdiffusenormal, avg;
3491 vec_t f, fa, fd, fdd;
3493 for (i = 0;i < r_refdef.scene.numentities;i++)
3495 ent = r_refdef.scene.entities[i];
3497 // skip unseen models
3498 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3502 if (ent->model && ent->model->brush.num_leafs)
3504 // TODO: use modellight for r_ambient settings on world?
3505 VectorSet(ent->modellight_ambient, 0, 0, 0);
3506 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3507 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3511 // fetch the lighting from the worldmodel data
3512 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));
3513 VectorClear(ent->modellight_diffuse);
3514 VectorClear(tempdiffusenormal);
3515 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3518 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3519 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3520 if(ent->flags & RENDER_EQUALIZE)
3522 // first fix up ambient lighting...
3523 if(r_equalize_entities_minambient.value > 0)
3525 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3528 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3529 if(fa < r_equalize_entities_minambient.value * fd)
3532 // fa'/fd' = minambient
3533 // fa'+0.25*fd' = fa+0.25*fd
3535 // fa' = fd' * minambient
3536 // fd'*(0.25+minambient) = fa+0.25*fd
3538 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3539 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3541 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3542 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
3543 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3544 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3549 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3551 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3552 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3555 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3556 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3557 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3563 VectorSet(ent->modellight_ambient, 1, 1, 1);
3565 // move the light direction into modelspace coordinates for lighting code
3566 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3567 if(VectorLength2(ent->modellight_lightdir) == 0)
3568 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3569 VectorNormalize(ent->modellight_lightdir);
3573 #define MAX_LINEOFSIGHTTRACES 64
3575 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3578 vec3_t boxmins, boxmaxs;
3581 dp_model_t *model = r_refdef.scene.worldmodel;
3583 if (!model || !model->brush.TraceLineOfSight)
3586 // expand the box a little
3587 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3588 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3589 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3590 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3591 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3592 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3595 VectorCopy(eye, start);
3596 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3597 if (model->brush.TraceLineOfSight(model, start, end))
3600 // try various random positions
3601 for (i = 0;i < numsamples;i++)
3603 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3604 if (model->brush.TraceLineOfSight(model, start, end))
3612 static void R_View_UpdateEntityVisible (void)
3617 entity_render_t *ent;
3619 if (!r_drawentities.integer)
3622 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3623 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3625 // worldmodel can check visibility
3626 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3627 for (i = 0;i < r_refdef.scene.numentities;i++)
3629 ent = r_refdef.scene.entities[i];
3630 if (!(ent->flags & renderimask))
3631 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)))
3632 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))
3633 r_refdef.viewcache.entityvisible[i] = true;
3635 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3637 for (i = 0;i < r_refdef.scene.numentities;i++)
3639 ent = r_refdef.scene.entities[i];
3640 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3642 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3644 continue; // temp entities do pvs only
3645 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3646 ent->last_trace_visibility = realtime;
3647 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3648 r_refdef.viewcache.entityvisible[i] = 0;
3655 // no worldmodel or it can't check visibility
3656 for (i = 0;i < r_refdef.scene.numentities;i++)
3658 ent = r_refdef.scene.entities[i];
3659 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));
3664 /// only used if skyrendermasked, and normally returns false
3665 int R_DrawBrushModelsSky (void)
3668 entity_render_t *ent;
3670 if (!r_drawentities.integer)
3674 for (i = 0;i < r_refdef.scene.numentities;i++)
3676 if (!r_refdef.viewcache.entityvisible[i])
3678 ent = r_refdef.scene.entities[i];
3679 if (!ent->model || !ent->model->DrawSky)
3681 ent->model->DrawSky(ent);
3687 static void R_DrawNoModel(entity_render_t *ent);
3688 static void R_DrawModels(void)
3691 entity_render_t *ent;
3693 if (!r_drawentities.integer)
3696 for (i = 0;i < r_refdef.scene.numentities;i++)
3698 if (!r_refdef.viewcache.entityvisible[i])
3700 ent = r_refdef.scene.entities[i];
3701 r_refdef.stats.entities++;
3702 if (ent->model && ent->model->Draw != NULL)
3703 ent->model->Draw(ent);
3709 static void R_DrawModelsDepth(void)
3712 entity_render_t *ent;
3714 if (!r_drawentities.integer)
3717 for (i = 0;i < r_refdef.scene.numentities;i++)
3719 if (!r_refdef.viewcache.entityvisible[i])
3721 ent = r_refdef.scene.entities[i];
3722 if (ent->model && ent->model->DrawDepth != NULL)
3723 ent->model->DrawDepth(ent);
3727 static void R_DrawModelsDebug(void)
3730 entity_render_t *ent;
3732 if (!r_drawentities.integer)
3735 for (i = 0;i < r_refdef.scene.numentities;i++)
3737 if (!r_refdef.viewcache.entityvisible[i])
3739 ent = r_refdef.scene.entities[i];
3740 if (ent->model && ent->model->DrawDebug != NULL)
3741 ent->model->DrawDebug(ent);
3745 static void R_DrawModelsAddWaterPlanes(void)
3748 entity_render_t *ent;
3750 if (!r_drawentities.integer)
3753 for (i = 0;i < r_refdef.scene.numentities;i++)
3755 if (!r_refdef.viewcache.entityvisible[i])
3757 ent = r_refdef.scene.entities[i];
3758 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3759 ent->model->DrawAddWaterPlanes(ent);
3763 static void R_View_SetFrustum(void)
3766 double slopex, slopey;
3767 vec3_t forward, left, up, origin;
3769 // we can't trust r_refdef.view.forward and friends in reflected scenes
3770 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3773 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3774 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3775 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3776 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3777 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3778 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3779 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3780 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3781 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3782 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3783 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3784 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3788 zNear = r_refdef.nearclip;
3789 nudge = 1.0 - 1.0 / (1<<23);
3790 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3791 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3792 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3793 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3794 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3795 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3796 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3797 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3803 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3804 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3805 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3806 r_refdef.view.frustum[0].dist = m[15] - m[12];
3808 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3809 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3810 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3811 r_refdef.view.frustum[1].dist = m[15] + m[12];
3813 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3814 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3815 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3816 r_refdef.view.frustum[2].dist = m[15] - m[13];
3818 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3819 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3820 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3821 r_refdef.view.frustum[3].dist = m[15] + m[13];
3823 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3824 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3825 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3826 r_refdef.view.frustum[4].dist = m[15] - m[14];
3828 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3829 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3830 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3831 r_refdef.view.frustum[5].dist = m[15] + m[14];
3834 if (r_refdef.view.useperspective)
3836 slopex = 1.0 / r_refdef.view.frustum_x;
3837 slopey = 1.0 / r_refdef.view.frustum_y;
3838 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3839 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3840 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3841 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3842 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3844 // Leaving those out was a mistake, those were in the old code, and they
3845 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3846 // I couldn't reproduce it after adding those normalizations. --blub
3847 VectorNormalize(r_refdef.view.frustum[0].normal);
3848 VectorNormalize(r_refdef.view.frustum[1].normal);
3849 VectorNormalize(r_refdef.view.frustum[2].normal);
3850 VectorNormalize(r_refdef.view.frustum[3].normal);
3852 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3853 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]);
3854 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]);
3855 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]);
3856 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]);
3858 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3859 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3860 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3861 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3862 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3866 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3867 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3868 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3869 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3870 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3871 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3872 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3873 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3874 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3875 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3877 r_refdef.view.numfrustumplanes = 5;
3879 if (r_refdef.view.useclipplane)
3881 r_refdef.view.numfrustumplanes = 6;
3882 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3885 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3886 PlaneClassify(r_refdef.view.frustum + i);
3888 // LordHavoc: note to all quake engine coders, Quake had a special case
3889 // for 90 degrees which assumed a square view (wrong), so I removed it,
3890 // Quake2 has it disabled as well.
3892 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3893 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3894 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3895 //PlaneClassify(&frustum[0]);
3897 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3898 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3899 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3900 //PlaneClassify(&frustum[1]);
3902 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3903 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3904 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3905 //PlaneClassify(&frustum[2]);
3907 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3908 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3909 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3910 //PlaneClassify(&frustum[3]);
3913 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3914 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3915 //PlaneClassify(&frustum[4]);
3918 void R_View_Update(void)
3920 R_Main_ResizeViewCache();
3921 R_View_SetFrustum();
3922 R_View_WorldVisibility(r_refdef.view.useclipplane);
3923 R_View_UpdateEntityVisible();
3924 R_View_UpdateEntityLighting();
3927 void R_SetupView(qboolean allowwaterclippingplane)
3929 const double *customclipplane = NULL;
3931 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3933 // LordHavoc: couldn't figure out how to make this approach the
3934 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3935 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3936 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3937 dist = r_refdef.view.clipplane.dist;
3938 plane[0] = r_refdef.view.clipplane.normal[0];
3939 plane[1] = r_refdef.view.clipplane.normal[1];
3940 plane[2] = r_refdef.view.clipplane.normal[2];
3942 customclipplane = plane;
3945 if (!r_refdef.view.useperspective)
3946 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);
3947 else if (vid.stencil && r_useinfinitefarclip.integer)
3948 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);
3950 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);
3951 R_SetViewport(&r_refdef.view.viewport);
3954 void R_ResetViewRendering2D(void)
3956 r_viewport_t viewport;
3959 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3960 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);
3961 R_SetViewport(&viewport);
3962 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3963 GL_Color(1, 1, 1, 1);
3964 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3965 GL_BlendFunc(GL_ONE, GL_ZERO);
3966 GL_AlphaTest(false);
3967 GL_ScissorTest(false);
3968 GL_DepthMask(false);
3969 GL_DepthRange(0, 1);
3970 GL_DepthTest(false);
3971 R_Mesh_Matrix(&identitymatrix);
3972 R_Mesh_ResetTextureState();
3973 GL_PolygonOffset(0, 0);
3974 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3975 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3976 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3977 qglStencilMask(~0);CHECKGLERROR
3978 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3979 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3980 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3981 R_SetupGenericShader(true);
3984 void R_ResetViewRendering3D(void)
3989 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3990 GL_Color(1, 1, 1, 1);
3991 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3992 GL_BlendFunc(GL_ONE, GL_ZERO);
3993 GL_AlphaTest(false);
3994 GL_ScissorTest(true);
3996 GL_DepthRange(0, 1);
3998 R_Mesh_Matrix(&identitymatrix);
3999 R_Mesh_ResetTextureState();
4000 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4001 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4002 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4003 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4004 qglStencilMask(~0);CHECKGLERROR
4005 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4006 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4007 GL_CullFace(r_refdef.view.cullface_back);
4008 R_SetupGenericShader(true);
4011 void R_RenderScene(void);
4012 void R_RenderWaterPlanes(void);
4014 static void R_Water_StartFrame(void)
4017 int waterwidth, waterheight, texturewidth, textureheight;
4018 r_waterstate_waterplane_t *p;
4020 // set waterwidth and waterheight to the water resolution that will be
4021 // used (often less than the screen resolution for faster rendering)
4022 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
4023 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
4025 // calculate desired texture sizes
4026 // can't use water if the card does not support the texture size
4027 if (!r_water.integer || !r_glsl.integer || !vid.support.arb_fragment_shader || waterwidth > (int)vid.maxtexturesize_2d || waterheight > (int)vid.maxtexturesize_2d || r_showsurfaces.integer)
4028 texturewidth = textureheight = waterwidth = waterheight = 0;
4029 else if (vid.support.arb_texture_non_power_of_two)
4031 texturewidth = waterwidth;
4032 textureheight = waterheight;
4036 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4037 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4040 // allocate textures as needed
4041 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4043 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4044 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4046 if (p->texture_refraction)
4047 R_FreeTexture(p->texture_refraction);
4048 p->texture_refraction = NULL;
4049 if (p->texture_reflection)
4050 R_FreeTexture(p->texture_reflection);
4051 p->texture_reflection = NULL;
4053 memset(&r_waterstate, 0, sizeof(r_waterstate));
4054 r_waterstate.texturewidth = texturewidth;
4055 r_waterstate.textureheight = textureheight;
4058 if (r_waterstate.texturewidth)
4060 r_waterstate.enabled = true;
4062 // when doing a reduced render (HDR) we want to use a smaller area
4063 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4064 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4066 // set up variables that will be used in shader setup
4067 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4068 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4069 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4070 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4073 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4074 r_waterstate.numwaterplanes = 0;
4077 void R_Water_AddWaterPlane(msurface_t *surface)
4079 int triangleindex, planeindex;
4085 r_waterstate_waterplane_t *p;
4086 texture_t *t = R_GetCurrentTexture(surface->texture);
4087 // just use the first triangle with a valid normal for any decisions
4088 VectorClear(normal);
4089 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4091 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4092 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4093 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4094 TriangleNormal(vert[0], vert[1], vert[2], normal);
4095 if (VectorLength2(normal) >= 0.001)
4099 VectorCopy(normal, plane.normal);
4100 VectorNormalize(plane.normal);
4101 plane.dist = DotProduct(vert[0], plane.normal);
4102 PlaneClassify(&plane);
4103 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4105 // skip backfaces (except if nocullface is set)
4106 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4108 VectorNegate(plane.normal, plane.normal);
4110 PlaneClassify(&plane);
4114 // find a matching plane if there is one
4115 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4116 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4118 if (planeindex >= r_waterstate.maxwaterplanes)
4119 return; // nothing we can do, out of planes
4121 // if this triangle does not fit any known plane rendered this frame, add one
4122 if (planeindex >= r_waterstate.numwaterplanes)
4124 // store the new plane
4125 r_waterstate.numwaterplanes++;
4127 // clear materialflags and pvs
4128 p->materialflags = 0;
4129 p->pvsvalid = false;
4131 // merge this surface's materialflags into the waterplane
4132 p->materialflags |= t->currentmaterialflags;
4133 // merge this surface's PVS into the waterplane
4134 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4135 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4136 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4138 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4143 static void R_Water_ProcessPlanes(void)
4145 r_refdef_view_t originalview;
4146 r_refdef_view_t myview;
4148 r_waterstate_waterplane_t *p;
4150 originalview = r_refdef.view;
4152 // make sure enough textures are allocated
4153 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4155 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4157 if (!p->texture_refraction)
4158 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);
4159 if (!p->texture_refraction)
4163 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4165 if (!p->texture_reflection)
4166 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);
4167 if (!p->texture_reflection)
4173 r_refdef.view = originalview;
4174 r_refdef.view.showdebug = false;
4175 r_refdef.view.width = r_waterstate.waterwidth;
4176 r_refdef.view.height = r_waterstate.waterheight;
4177 r_refdef.view.useclipplane = true;
4178 myview = r_refdef.view;
4179 r_waterstate.renderingscene = true;
4180 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4182 // render the normal view scene and copy into texture
4183 // (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)
4184 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4186 r_refdef.view = myview;
4187 r_refdef.view.clipplane = p->plane;
4188 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4189 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4190 PlaneClassify(&r_refdef.view.clipplane);
4192 R_ResetViewRendering3D();
4193 R_ClearScreen(r_refdef.fogenabled);
4197 // copy view into the screen texture
4198 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4199 GL_ActiveTexture(0);
4201 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
4204 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4206 r_refdef.view = myview;
4207 // render reflected scene and copy into texture
4208 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4209 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4210 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4211 r_refdef.view.clipplane = p->plane;
4212 // reverse the cullface settings for this render
4213 r_refdef.view.cullface_front = GL_FRONT;
4214 r_refdef.view.cullface_back = GL_BACK;
4215 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4217 r_refdef.view.usecustompvs = true;
4219 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4221 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4224 R_ResetViewRendering3D();
4225 R_ClearScreen(r_refdef.fogenabled);
4229 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4230 GL_ActiveTexture(0);
4232 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
4235 r_waterstate.renderingscene = false;
4236 r_refdef.view = originalview;
4237 R_ResetViewRendering3D();
4238 R_ClearScreen(r_refdef.fogenabled);
4242 r_refdef.view = originalview;
4243 r_waterstate.renderingscene = false;
4244 Cvar_SetValueQuick(&r_water, 0);
4245 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4249 void R_Bloom_StartFrame(void)
4251 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4253 // set bloomwidth and bloomheight to the bloom resolution that will be
4254 // used (often less than the screen resolution for faster rendering)
4255 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4256 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4257 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4258 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
4259 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
4261 // calculate desired texture sizes
4262 if (vid.support.arb_texture_non_power_of_two)
4264 screentexturewidth = r_refdef.view.width;
4265 screentextureheight = r_refdef.view.height;
4266 bloomtexturewidth = r_bloomstate.bloomwidth;
4267 bloomtextureheight = r_bloomstate.bloomheight;
4271 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4272 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4273 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4274 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4277 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 > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
4279 Cvar_SetValueQuick(&r_hdr, 0);
4280 Cvar_SetValueQuick(&r_bloom, 0);
4281 Cvar_SetValueQuick(&r_motionblur, 0);
4282 Cvar_SetValueQuick(&r_damageblur, 0);
4285 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)))
4286 screentexturewidth = screentextureheight = 0;
4287 if (!r_hdr.integer && !r_bloom.integer)
4288 bloomtexturewidth = bloomtextureheight = 0;
4290 // allocate textures as needed
4291 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4293 if (r_bloomstate.texture_screen)
4294 R_FreeTexture(r_bloomstate.texture_screen);
4295 r_bloomstate.texture_screen = NULL;
4296 r_bloomstate.screentexturewidth = screentexturewidth;
4297 r_bloomstate.screentextureheight = screentextureheight;
4298 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4299 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);
4301 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4303 if (r_bloomstate.texture_bloom)
4304 R_FreeTexture(r_bloomstate.texture_bloom);
4305 r_bloomstate.texture_bloom = NULL;
4306 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4307 r_bloomstate.bloomtextureheight = bloomtextureheight;
4308 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4309 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);
4312 // when doing a reduced render (HDR) we want to use a smaller area
4313 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4314 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4315 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4316 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4317 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4319 // set up a texcoord array for the full resolution screen image
4320 // (we have to keep this around to copy back during final render)
4321 r_bloomstate.screentexcoord2f[0] = 0;
4322 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4323 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4324 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4325 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4326 r_bloomstate.screentexcoord2f[5] = 0;
4327 r_bloomstate.screentexcoord2f[6] = 0;
4328 r_bloomstate.screentexcoord2f[7] = 0;
4330 // set up a texcoord array for the reduced resolution bloom image
4331 // (which will be additive blended over the screen image)
4332 r_bloomstate.bloomtexcoord2f[0] = 0;
4333 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4334 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4335 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4336 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4337 r_bloomstate.bloomtexcoord2f[5] = 0;
4338 r_bloomstate.bloomtexcoord2f[6] = 0;
4339 r_bloomstate.bloomtexcoord2f[7] = 0;
4341 if (r_hdr.integer || r_bloom.integer)
4343 r_bloomstate.enabled = true;
4344 r_bloomstate.hdr = r_hdr.integer != 0;
4347 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);
4350 void R_Bloom_CopyBloomTexture(float colorscale)
4352 r_refdef.stats.bloom++;
4354 // scale down screen texture to the bloom texture size
4356 R_SetViewport(&r_bloomstate.viewport);
4357 GL_BlendFunc(GL_ONE, GL_ZERO);
4358 GL_Color(colorscale, colorscale, colorscale, 1);
4359 // TODO: optimize with multitexture or GLSL
4360 R_SetupGenericShader(true);
4361 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4362 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4363 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4364 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4366 // we now have a bloom image in the framebuffer
4367 // copy it into the bloom image texture for later processing
4368 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4369 GL_ActiveTexture(0);
4371 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4372 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4375 void R_Bloom_CopyHDRTexture(void)
4377 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4378 GL_ActiveTexture(0);
4380 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
4381 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4384 void R_Bloom_MakeTexture(void)
4387 float xoffset, yoffset, r, brighten;
4389 r_refdef.stats.bloom++;
4391 R_ResetViewRendering2D();
4392 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4393 R_Mesh_ColorPointer(NULL, 0, 0);
4394 R_SetupGenericShader(true);
4396 // we have a bloom image in the framebuffer
4398 R_SetViewport(&r_bloomstate.viewport);
4400 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4403 r = bound(0, r_bloom_colorexponent.value / x, 1);
4404 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4405 GL_Color(r, r, r, 1);
4406 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4407 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4408 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4409 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4411 // copy the vertically blurred bloom view to a texture
4412 GL_ActiveTexture(0);
4414 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4415 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4418 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4419 brighten = r_bloom_brighten.value;
4421 brighten *= r_hdr_range.value;
4422 brighten = sqrt(brighten);
4424 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4425 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4426 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4428 for (dir = 0;dir < 2;dir++)
4430 // blend on at multiple vertical offsets to achieve a vertical blur
4431 // TODO: do offset blends using GLSL
4432 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4433 GL_BlendFunc(GL_ONE, GL_ZERO);
4434 for (x = -range;x <= range;x++)
4436 if (!dir){xoffset = 0;yoffset = x;}
4437 else {xoffset = x;yoffset = 0;}
4438 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4439 yoffset /= (float)r_bloomstate.bloomtextureheight;
4440 // compute a texcoord array with the specified x and y offset
4441 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4442 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4443 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4444 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4445 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4446 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4447 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4448 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4449 // this r value looks like a 'dot' particle, fading sharply to
4450 // black at the edges
4451 // (probably not realistic but looks good enough)
4452 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4453 //r = brighten/(range*2+1);
4454 r = brighten / (range * 2 + 1);
4456 r *= (1 - x*x/(float)(range*range));
4457 GL_Color(r, r, r, 1);
4458 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4459 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4460 GL_BlendFunc(GL_ONE, GL_ONE);
4463 // copy the vertically blurred bloom view to a texture
4464 GL_ActiveTexture(0);
4466 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4467 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4470 // apply subtract last
4471 // (just like it would be in a GLSL shader)
4472 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
4474 GL_BlendFunc(GL_ONE, GL_ZERO);
4475 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4476 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4477 GL_Color(1, 1, 1, 1);
4478 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4479 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4481 GL_BlendFunc(GL_ONE, GL_ONE);
4482 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4483 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4484 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4485 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4486 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4487 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4488 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4490 // copy the darkened bloom view to a texture
4491 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4492 GL_ActiveTexture(0);
4494 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4495 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4499 void R_HDR_RenderBloomTexture(void)
4501 int oldwidth, oldheight;
4502 float oldcolorscale;
4504 oldcolorscale = r_refdef.view.colorscale;
4505 oldwidth = r_refdef.view.width;
4506 oldheight = r_refdef.view.height;
4507 r_refdef.view.width = r_bloomstate.bloomwidth;
4508 r_refdef.view.height = r_bloomstate.bloomheight;
4510 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4511 // TODO: add exposure compensation features
4512 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4514 r_refdef.view.showdebug = false;
4515 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4517 R_ResetViewRendering3D();
4519 R_ClearScreen(r_refdef.fogenabled);
4520 if (r_timereport_active)
4521 R_TimeReport("HDRclear");
4524 if (r_timereport_active)
4525 R_TimeReport("visibility");
4527 // only do secondary renders with HDR if r_hdr is 2 or higher
4528 r_waterstate.numwaterplanes = 0;
4529 if (r_waterstate.enabled && r_hdr.integer >= 2)
4530 R_RenderWaterPlanes();
4532 r_refdef.view.showdebug = true;
4534 r_waterstate.numwaterplanes = 0;
4536 R_ResetViewRendering2D();
4538 R_Bloom_CopyHDRTexture();
4539 R_Bloom_MakeTexture();
4541 // restore the view settings
4542 r_refdef.view.width = oldwidth;
4543 r_refdef.view.height = oldheight;
4544 r_refdef.view.colorscale = oldcolorscale;
4546 R_ResetViewRendering3D();
4548 R_ClearScreen(r_refdef.fogenabled);
4549 if (r_timereport_active)
4550 R_TimeReport("viewclear");
4553 static void R_BlendView(void)
4555 if (r_bloomstate.texture_screen)
4557 // make sure the buffer is available
4558 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4560 R_ResetViewRendering2D();
4561 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4562 R_Mesh_ColorPointer(NULL, 0, 0);
4563 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4564 GL_ActiveTexture(0);CHECKGLERROR
4566 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4568 // declare variables
4570 static float avgspeed;
4572 speed = VectorLength(cl.movement_velocity);
4574 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4575 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4577 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4578 speed = bound(0, speed, 1);
4579 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4581 // calculate values into a standard alpha
4582 cl.motionbluralpha = 1 - exp(-
4584 (r_motionblur.value * speed / 80)
4586 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4589 max(0.0001, cl.time - cl.oldtime) // fps independent
4592 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4593 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4595 if (cl.motionbluralpha > 0)
4597 R_SetupGenericShader(true);
4598 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4599 GL_Color(1, 1, 1, cl.motionbluralpha);
4600 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4601 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4602 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4603 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4607 // copy view into the screen texture
4608 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
4609 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4612 if (r_glsl.integer && vid.support.arb_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4614 unsigned int permutation =
4615 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4616 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4617 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4618 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4619 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4621 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4623 // render simple bloom effect
4624 // copy the screen and shrink it and darken it for the bloom process
4625 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4626 // make the bloom texture
4627 R_Bloom_MakeTexture();
4630 R_ResetViewRendering2D();
4631 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4632 R_Mesh_ColorPointer(NULL, 0, 0);
4633 GL_Color(1, 1, 1, 1);
4634 GL_BlendFunc(GL_ONE, GL_ZERO);
4635 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4636 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4637 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4638 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4639 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4640 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4641 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4642 if (r_glsl_permutation->loc_TintColor >= 0)
4643 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4644 if (r_glsl_permutation->loc_ClientTime >= 0)
4645 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4646 if (r_glsl_permutation->loc_PixelSize >= 0)
4647 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4648 if (r_glsl_permutation->loc_UserVec1 >= 0)
4650 float a=0, b=0, c=0, d=0;
4651 #if _MSC_VER >= 1400
4652 #define sscanf sscanf_s
4654 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4655 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4657 if (r_glsl_permutation->loc_UserVec2 >= 0)
4659 float a=0, b=0, c=0, d=0;
4660 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4661 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4663 if (r_glsl_permutation->loc_UserVec3 >= 0)
4665 float a=0, b=0, c=0, d=0;
4666 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4667 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4669 if (r_glsl_permutation->loc_UserVec4 >= 0)
4671 float a=0, b=0, c=0, d=0;
4672 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4673 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4675 if (r_glsl_permutation->loc_Saturation >= 0)
4676 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4677 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4678 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4684 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4686 // render high dynamic range bloom effect
4687 // the bloom texture was made earlier this render, so we just need to
4688 // blend it onto the screen...
4689 R_ResetViewRendering2D();
4690 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4691 R_Mesh_ColorPointer(NULL, 0, 0);
4692 R_SetupGenericShader(true);
4693 GL_Color(1, 1, 1, 1);
4694 GL_BlendFunc(GL_ONE, GL_ONE);
4695 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4696 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4697 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4698 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4700 else if (r_bloomstate.texture_bloom)
4702 // render simple bloom effect
4703 // copy the screen and shrink it and darken it for the bloom process
4704 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4705 // make the bloom texture
4706 R_Bloom_MakeTexture();
4707 // put the original screen image back in place and blend the bloom
4709 R_ResetViewRendering2D();
4710 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4711 R_Mesh_ColorPointer(NULL, 0, 0);
4712 GL_Color(1, 1, 1, 1);
4713 GL_BlendFunc(GL_ONE, GL_ZERO);
4714 // do both in one pass if possible
4715 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4716 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4717 if (r_textureunits.integer >= 2 && gl_combine.integer)
4719 R_SetupGenericTwoTextureShader(GL_ADD);
4720 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4721 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4725 R_SetupGenericShader(true);
4726 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4727 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4728 // now blend on the bloom texture
4729 GL_BlendFunc(GL_ONE, GL_ONE);
4730 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4731 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4733 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4734 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4736 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4738 // apply a color tint to the whole view
4739 R_ResetViewRendering2D();
4740 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4741 R_Mesh_ColorPointer(NULL, 0, 0);
4742 R_SetupGenericShader(false);
4743 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4744 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4745 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4749 matrix4x4_t r_waterscrollmatrix;
4751 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4753 if (r_refdef.fog_density)
4755 r_refdef.fogcolor[0] = r_refdef.fog_red;
4756 r_refdef.fogcolor[1] = r_refdef.fog_green;
4757 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4759 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4760 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4761 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4762 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4766 VectorCopy(r_refdef.fogcolor, fogvec);
4767 // color.rgb *= ContrastBoost * SceneBrightness;
4768 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4769 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4770 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4771 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4776 void R_UpdateVariables(void)
4780 r_refdef.scene.ambient = r_ambient.value;
4782 r_refdef.farclip = r_farclip_base.value;
4783 if (r_refdef.scene.worldmodel)
4784 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
4785 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4787 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4788 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4789 r_refdef.polygonfactor = 0;
4790 r_refdef.polygonoffset = 0;
4791 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4792 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4794 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4795 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
4796 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4797 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
4798 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4799 if (r_showsurfaces.integer)
4801 r_refdef.scene.rtworld = false;
4802 r_refdef.scene.rtworldshadows = false;
4803 r_refdef.scene.rtdlight = false;
4804 r_refdef.scene.rtdlightshadows = false;
4805 r_refdef.lightmapintensity = 0;
4808 if (gamemode == GAME_NEHAHRA)
4810 if (gl_fogenable.integer)
4812 r_refdef.oldgl_fogenable = true;
4813 r_refdef.fog_density = gl_fogdensity.value;
4814 r_refdef.fog_red = gl_fogred.value;
4815 r_refdef.fog_green = gl_foggreen.value;
4816 r_refdef.fog_blue = gl_fogblue.value;
4817 r_refdef.fog_alpha = 1;
4818 r_refdef.fog_start = 0;
4819 r_refdef.fog_end = gl_skyclip.value;
4820 r_refdef.fog_height = 1<<30;
4821 r_refdef.fog_fadedepth = 128;
4823 else if (r_refdef.oldgl_fogenable)
4825 r_refdef.oldgl_fogenable = false;
4826 r_refdef.fog_density = 0;
4827 r_refdef.fog_red = 0;
4828 r_refdef.fog_green = 0;
4829 r_refdef.fog_blue = 0;
4830 r_refdef.fog_alpha = 0;
4831 r_refdef.fog_start = 0;
4832 r_refdef.fog_end = 0;
4833 r_refdef.fog_height = 1<<30;
4834 r_refdef.fog_fadedepth = 128;
4838 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4839 r_refdef.fog_start = max(0, r_refdef.fog_start);
4840 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4842 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4844 if (r_refdef.fog_density && r_drawfog.integer)
4846 r_refdef.fogenabled = true;
4847 // this is the point where the fog reaches 0.9986 alpha, which we
4848 // consider a good enough cutoff point for the texture
4849 // (0.9986 * 256 == 255.6)
4850 if (r_fog_exp2.integer)
4851 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4853 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4854 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4855 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4856 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4857 // fog color was already set
4858 // update the fog texture
4859 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)
4860 R_BuildFogTexture();
4863 r_refdef.fogenabled = false;
4865 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4867 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4869 // build GLSL gamma texture
4870 #define RAMPWIDTH 256
4871 unsigned short ramp[RAMPWIDTH * 3];
4872 unsigned char rampbgr[RAMPWIDTH][4];
4875 r_texture_gammaramps_serial = vid_gammatables_serial;
4877 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4878 for(i = 0; i < RAMPWIDTH; ++i)
4880 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4881 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4882 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4885 if (r_texture_gammaramps)
4887 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4891 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);
4897 // remove GLSL gamma texture
4901 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4902 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4908 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4909 if( scenetype != r_currentscenetype ) {
4910 // store the old scenetype
4911 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4912 r_currentscenetype = scenetype;
4913 // move in the new scene
4914 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4923 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4925 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4926 if( scenetype == r_currentscenetype ) {
4927 return &r_refdef.scene;
4929 return &r_scenes_store[ scenetype ];
4938 void R_RenderView(void)
4940 if (r_timereport_active)
4941 R_TimeReport("start");
4942 r_frame++; // used only by R_GetCurrentTexture
4943 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4945 R_AnimCache_NewFrame();
4947 if (r_refdef.view.isoverlay)
4949 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4950 GL_Clear( GL_DEPTH_BUFFER_BIT );
4951 R_TimeReport("depthclear");
4953 r_refdef.view.showdebug = false;
4955 r_waterstate.enabled = false;
4956 r_waterstate.numwaterplanes = 0;
4964 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4965 return; //Host_Error ("R_RenderView: NULL worldmodel");
4967 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4969 // break apart the view matrix into vectors for various purposes
4970 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4971 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4972 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4973 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4974 // make an inverted copy of the view matrix for tracking sprites
4975 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4977 R_Shadow_UpdateWorldLightSelection();
4979 R_Bloom_StartFrame();
4980 R_Water_StartFrame();
4983 if (r_timereport_active)
4984 R_TimeReport("viewsetup");
4986 R_ResetViewRendering3D();
4988 if (r_refdef.view.clear || r_refdef.fogenabled)
4990 R_ClearScreen(r_refdef.fogenabled);
4991 if (r_timereport_active)
4992 R_TimeReport("viewclear");
4994 r_refdef.view.clear = true;
4996 // this produces a bloom texture to be used in R_BlendView() later
4997 if (r_hdr.integer && r_bloomstate.bloomwidth)
4998 R_HDR_RenderBloomTexture();
5000 r_refdef.view.showdebug = true;
5003 if (r_timereport_active)
5004 R_TimeReport("visibility");
5006 r_waterstate.numwaterplanes = 0;
5007 if (r_waterstate.enabled)
5008 R_RenderWaterPlanes();
5011 r_waterstate.numwaterplanes = 0;
5014 if (r_timereport_active)
5015 R_TimeReport("blendview");
5017 GL_Scissor(0, 0, vid.width, vid.height);
5018 GL_ScissorTest(false);
5022 void R_RenderWaterPlanes(void)
5024 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5026 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5027 if (r_timereport_active)
5028 R_TimeReport("waterworld");
5031 // don't let sound skip if going slow
5032 if (r_refdef.scene.extraupdate)
5035 R_DrawModelsAddWaterPlanes();
5036 if (r_timereport_active)
5037 R_TimeReport("watermodels");
5039 if (r_waterstate.numwaterplanes)
5041 R_Water_ProcessPlanes();
5042 if (r_timereport_active)
5043 R_TimeReport("waterscenes");
5047 extern void R_DrawLightningBeams (void);
5048 extern void VM_CL_AddPolygonsToMeshQueue (void);
5049 extern void R_DrawPortals (void);
5050 extern cvar_t cl_locs_show;
5051 static void R_DrawLocs(void);
5052 static void R_DrawEntityBBoxes(void);
5053 static void R_DrawModelDecals(void);
5054 extern cvar_t cl_decals_newsystem;
5055 void R_RenderScene(void)
5057 r_refdef.stats.renders++;
5061 // don't let sound skip if going slow
5062 if (r_refdef.scene.extraupdate)
5065 R_MeshQueue_BeginScene();
5069 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);
5071 if (cl.csqc_vidvars.drawworld)
5073 // don't let sound skip if going slow
5074 if (r_refdef.scene.extraupdate)
5077 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5079 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5080 if (r_timereport_active)
5081 R_TimeReport("worldsky");
5084 if (R_DrawBrushModelsSky() && r_timereport_active)
5085 R_TimeReport("bmodelsky");
5087 if (skyrendermasked && skyrenderlater)
5089 // we have to force off the water clipping plane while rendering sky
5096 R_AnimCache_CacheVisibleEntities();
5098 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5100 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5101 if (r_timereport_active)
5102 R_TimeReport("worlddepth");
5104 if (r_depthfirst.integer >= 2)
5106 R_DrawModelsDepth();
5107 if (r_timereport_active)
5108 R_TimeReport("modeldepth");
5111 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5113 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5114 if (r_timereport_active)
5115 R_TimeReport("world");
5118 // don't let sound skip if going slow
5119 if (r_refdef.scene.extraupdate)
5123 if (r_timereport_active)
5124 R_TimeReport("models");
5126 // don't let sound skip if going slow
5127 if (r_refdef.scene.extraupdate)
5130 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5132 R_DrawModelShadows();
5133 R_ResetViewRendering3D();
5134 // don't let sound skip if going slow
5135 if (r_refdef.scene.extraupdate)
5139 R_ShadowVolumeLighting(false);
5140 if (r_timereport_active)
5141 R_TimeReport("rtlights");
5143 // don't let sound skip if going slow
5144 if (r_refdef.scene.extraupdate)
5147 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5149 R_DrawModelShadows();
5150 R_ResetViewRendering3D();
5151 // don't let sound skip if going slow
5152 if (r_refdef.scene.extraupdate)
5156 if (cl.csqc_vidvars.drawworld)
5158 if (cl_decals_newsystem.integer)
5160 R_DrawModelDecals();
5161 if (r_timereport_active)
5162 R_TimeReport("modeldecals");
5167 if (r_timereport_active)
5168 R_TimeReport("decals");
5172 if (r_timereport_active)
5173 R_TimeReport("particles");
5176 if (r_timereport_active)
5177 R_TimeReport("explosions");
5179 R_DrawLightningBeams();
5180 if (r_timereport_active)
5181 R_TimeReport("lightning");
5184 R_SetupGenericShader(true);
5185 VM_CL_AddPolygonsToMeshQueue();
5187 if (r_refdef.view.showdebug)
5189 if (cl_locs_show.integer)
5192 if (r_timereport_active)
5193 R_TimeReport("showlocs");
5196 if (r_drawportals.integer)
5199 if (r_timereport_active)
5200 R_TimeReport("portals");
5203 if (r_showbboxes.value > 0)
5205 R_DrawEntityBBoxes();
5206 if (r_timereport_active)
5207 R_TimeReport("bboxes");
5211 R_SetupGenericShader(true);
5212 R_MeshQueue_RenderTransparent();
5213 if (r_timereport_active)
5214 R_TimeReport("drawtrans");
5216 R_SetupGenericShader(true);
5218 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))
5220 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5221 if (r_timereport_active)
5222 R_TimeReport("worlddebug");
5223 R_DrawModelsDebug();
5224 if (r_timereport_active)
5225 R_TimeReport("modeldebug");
5228 R_SetupGenericShader(true);
5230 if (cl.csqc_vidvars.drawworld)
5233 if (r_timereport_active)
5234 R_TimeReport("coronas");
5237 // don't let sound skip if going slow
5238 if (r_refdef.scene.extraupdate)
5241 R_ResetViewRendering2D();
5244 static const unsigned short bboxelements[36] =
5254 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5257 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5259 RSurf_ActiveWorldEntity();
5261 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5262 GL_DepthMask(false);
5263 GL_DepthRange(0, 1);
5264 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5265 R_Mesh_ResetTextureState();
5267 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5268 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5269 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5270 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5271 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5272 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5273 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5274 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5275 R_FillColors(color4f, 8, cr, cg, cb, ca);
5276 if (r_refdef.fogenabled)
5278 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5280 f1 = RSurf_FogVertex(v);
5282 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5283 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5284 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5287 R_Mesh_VertexPointer(vertex3f, 0, 0);
5288 R_Mesh_ColorPointer(color4f, 0, 0);
5289 R_Mesh_ResetTextureState();
5290 R_SetupGenericShader(false);
5291 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5294 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5298 prvm_edict_t *edict;
5299 prvm_prog_t *prog_save = prog;
5301 // this function draws bounding boxes of server entities
5305 GL_CullFace(GL_NONE);
5306 R_SetupGenericShader(false);
5310 for (i = 0;i < numsurfaces;i++)
5312 edict = PRVM_EDICT_NUM(surfacelist[i]);
5313 switch ((int)edict->fields.server->solid)
5315 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5316 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5317 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5318 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5319 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5320 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5322 color[3] *= r_showbboxes.value;
5323 color[3] = bound(0, color[3], 1);
5324 GL_DepthTest(!r_showdisabledepthtest.integer);
5325 GL_CullFace(r_refdef.view.cullface_front);
5326 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5332 static void R_DrawEntityBBoxes(void)
5335 prvm_edict_t *edict;
5337 prvm_prog_t *prog_save = prog;
5339 // this function draws bounding boxes of server entities
5345 for (i = 0;i < prog->num_edicts;i++)
5347 edict = PRVM_EDICT_NUM(i);
5348 if (edict->priv.server->free)
5350 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5351 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5353 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5355 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5356 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5362 static const int nomodelelement3i[24] =
5374 static const unsigned short nomodelelement3s[24] =
5386 static const float nomodelvertex3f[6*3] =
5396 static const float nomodelcolor4f[6*4] =
5398 0.0f, 0.0f, 0.5f, 1.0f,
5399 0.0f, 0.0f, 0.5f, 1.0f,
5400 0.0f, 0.5f, 0.0f, 1.0f,
5401 0.0f, 0.5f, 0.0f, 1.0f,
5402 0.5f, 0.0f, 0.0f, 1.0f,
5403 0.5f, 0.0f, 0.0f, 1.0f
5406 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5412 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);
5414 // this is only called once per entity so numsurfaces is always 1, and
5415 // surfacelist is always {0}, so this code does not handle batches
5417 if (rsurface.ent_flags & RENDER_ADDITIVE)
5419 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5420 GL_DepthMask(false);
5422 else if (rsurface.ent_color[3] < 1)
5424 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5425 GL_DepthMask(false);
5429 GL_BlendFunc(GL_ONE, GL_ZERO);
5432 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5433 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5434 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5435 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5436 R_SetupGenericShader(false);
5437 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5438 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5439 R_Mesh_ColorPointer(color4f, 0, 0);
5440 for (i = 0, c = color4f;i < 6;i++, c += 4)
5442 c[0] *= rsurface.ent_color[0];
5443 c[1] *= rsurface.ent_color[1];
5444 c[2] *= rsurface.ent_color[2];
5445 c[3] *= rsurface.ent_color[3];
5447 if (r_refdef.fogenabled)
5449 for (i = 0, c = color4f;i < 6;i++, c += 4)
5451 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5453 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5454 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5455 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5458 R_Mesh_ResetTextureState();
5459 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5462 void R_DrawNoModel(entity_render_t *ent)
5465 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5466 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5467 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5469 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5472 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5474 vec3_t right1, right2, diff, normal;
5476 VectorSubtract (org2, org1, normal);
5478 // calculate 'right' vector for start
5479 VectorSubtract (r_refdef.view.origin, org1, diff);
5480 CrossProduct (normal, diff, right1);
5481 VectorNormalize (right1);
5483 // calculate 'right' vector for end
5484 VectorSubtract (r_refdef.view.origin, org2, diff);
5485 CrossProduct (normal, diff, right2);
5486 VectorNormalize (right2);
5488 vert[ 0] = org1[0] + width * right1[0];
5489 vert[ 1] = org1[1] + width * right1[1];
5490 vert[ 2] = org1[2] + width * right1[2];
5491 vert[ 3] = org1[0] - width * right1[0];
5492 vert[ 4] = org1[1] - width * right1[1];
5493 vert[ 5] = org1[2] - width * right1[2];
5494 vert[ 6] = org2[0] - width * right2[0];
5495 vert[ 7] = org2[1] - width * right2[1];
5496 vert[ 8] = org2[2] - width * right2[2];
5497 vert[ 9] = org2[0] + width * right2[0];
5498 vert[10] = org2[1] + width * right2[1];
5499 vert[11] = org2[2] + width * right2[2];
5502 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)
5504 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5505 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5506 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5507 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5508 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5509 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5510 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5511 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5512 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5513 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5514 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5515 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5518 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5523 VectorSet(v, x, y, z);
5524 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5525 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5527 if (i == mesh->numvertices)
5529 if (mesh->numvertices < mesh->maxvertices)
5531 VectorCopy(v, vertex3f);
5532 mesh->numvertices++;
5534 return mesh->numvertices;
5540 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5544 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5545 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5546 e = mesh->element3i + mesh->numtriangles * 3;
5547 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5549 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5550 if (mesh->numtriangles < mesh->maxtriangles)
5555 mesh->numtriangles++;
5557 element[1] = element[2];
5561 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5565 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5566 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5567 e = mesh->element3i + mesh->numtriangles * 3;
5568 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5570 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5571 if (mesh->numtriangles < mesh->maxtriangles)
5576 mesh->numtriangles++;
5578 element[1] = element[2];
5582 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5583 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5585 int planenum, planenum2;
5588 mplane_t *plane, *plane2;
5590 double temppoints[2][256*3];
5591 // figure out how large a bounding box we need to properly compute this brush
5593 for (w = 0;w < numplanes;w++)
5594 maxdist = max(maxdist, fabs(planes[w].dist));
5595 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5596 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5597 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5601 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5602 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5604 if (planenum2 == planenum)
5606 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);
5609 if (tempnumpoints < 3)
5611 // generate elements forming a triangle fan for this polygon
5612 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5616 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)
5618 texturelayer_t *layer;
5619 layer = t->currentlayers + t->currentnumlayers++;
5621 layer->depthmask = depthmask;
5622 layer->blendfunc1 = blendfunc1;
5623 layer->blendfunc2 = blendfunc2;
5624 layer->texture = texture;
5625 layer->texmatrix = *matrix;
5626 layer->color[0] = r * r_refdef.view.colorscale;
5627 layer->color[1] = g * r_refdef.view.colorscale;
5628 layer->color[2] = b * r_refdef.view.colorscale;
5629 layer->color[3] = a;
5632 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5635 index = parms[2] + r_refdef.scene.time * parms[3];
5636 index -= floor(index);
5640 case Q3WAVEFUNC_NONE:
5641 case Q3WAVEFUNC_NOISE:
5642 case Q3WAVEFUNC_COUNT:
5645 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5646 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5647 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5648 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5649 case Q3WAVEFUNC_TRIANGLE:
5651 f = index - floor(index);
5662 return (float)(parms[0] + parms[1] * f);
5665 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5670 matrix4x4_t matrix, temp;
5671 switch(tcmod->tcmod)
5675 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5676 matrix = r_waterscrollmatrix;
5678 matrix = identitymatrix;
5680 case Q3TCMOD_ENTITYTRANSLATE:
5681 // this is used in Q3 to allow the gamecode to control texcoord
5682 // scrolling on the entity, which is not supported in darkplaces yet.
5683 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5685 case Q3TCMOD_ROTATE:
5686 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5687 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5688 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5691 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5693 case Q3TCMOD_SCROLL:
5694 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5696 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5697 w = (int) tcmod->parms[0];
5698 h = (int) tcmod->parms[1];
5699 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5701 idx = (int) floor(f * w * h);
5702 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5704 case Q3TCMOD_STRETCH:
5705 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5706 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5708 case Q3TCMOD_TRANSFORM:
5709 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5710 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5711 VectorSet(tcmat + 6, 0 , 0 , 1);
5712 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5713 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5715 case Q3TCMOD_TURBULENT:
5716 // this is handled in the RSurf_PrepareVertices function
5717 matrix = identitymatrix;
5721 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5724 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5726 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5727 char name[MAX_QPATH];
5728 skinframe_t *skinframe;
5729 unsigned char pixels[296*194];
5730 strlcpy(cache->name, skinname, sizeof(cache->name));
5731 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5732 if (developer_loading.integer)
5733 Con_Printf("loading %s\n", name);
5734 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5735 if (!skinframe || !skinframe->base)
5738 fs_offset_t filesize;
5740 f = FS_LoadFile(name, tempmempool, true, &filesize);
5743 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5744 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5748 cache->skinframe = skinframe;
5751 texture_t *R_GetCurrentTexture(texture_t *t)
5754 const entity_render_t *ent = rsurface.entity;
5755 dp_model_t *model = ent->model;
5756 q3shaderinfo_layer_tcmod_t *tcmod;
5758 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5759 return t->currentframe;
5760 t->update_lastrenderframe = r_frame;
5761 t->update_lastrenderentity = (void *)ent;
5763 // switch to an alternate material if this is a q1bsp animated material
5765 texture_t *texture = t;
5766 int s = rsurface.ent_skinnum;
5767 if ((unsigned int)s >= (unsigned int)model->numskins)
5769 if (model->skinscenes)
5771 if (model->skinscenes[s].framecount > 1)
5772 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5774 s = model->skinscenes[s].firstframe;
5777 t = t + s * model->num_surfaces;
5780 // use an alternate animation if the entity's frame is not 0,
5781 // and only if the texture has an alternate animation
5782 if (rsurface.ent_alttextures && t->anim_total[1])
5783 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5785 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5787 texture->currentframe = t;
5790 // update currentskinframe to be a qw skin or animation frame
5791 if (rsurface.ent_qwskin >= 0)
5793 i = rsurface.ent_qwskin;
5794 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5796 r_qwskincache_size = cl.maxclients;
5798 Mem_Free(r_qwskincache);
5799 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5801 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5802 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5803 t->currentskinframe = r_qwskincache[i].skinframe;
5804 if (t->currentskinframe == NULL)
5805 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5807 else if (t->numskinframes >= 2)
5808 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5809 if (t->backgroundnumskinframes >= 2)
5810 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5812 t->currentmaterialflags = t->basematerialflags;
5813 t->currentalpha = rsurface.ent_color[3];
5814 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5815 t->currentalpha *= r_wateralpha.value;
5816 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5817 t->currentalpha *= t->r_water_wateralpha;
5818 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5819 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5820 if (!(rsurface.ent_flags & RENDER_LIGHT))
5821 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5822 else if (rsurface.modeltexcoordlightmap2f == NULL)
5824 // pick a model lighting mode
5825 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5826 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5828 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5830 if (rsurface.ent_flags & RENDER_ADDITIVE)
5831 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5832 else if (t->currentalpha < 1)
5833 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5834 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5835 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5836 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5837 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5838 if (t->backgroundnumskinframes)
5839 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5840 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5842 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5843 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5846 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5848 // there is no tcmod
5849 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5851 t->currenttexmatrix = r_waterscrollmatrix;
5852 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5854 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
5856 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5857 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5860 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5861 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5862 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5863 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5865 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5866 if (t->currentskinframe->qpixels)
5867 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
5868 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5869 t->glosstexture = r_texture_black;
5870 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5871 t->backgroundglosstexture = r_texture_black;
5872 t->specularpower = r_shadow_glossexponent.value;
5873 // TODO: store reference values for these in the texture?
5874 t->specularscale = 0;
5875 if (r_shadow_gloss.integer > 0)
5877 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5879 if (r_shadow_glossintensity.value > 0)
5881 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5882 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5883 t->specularscale = r_shadow_glossintensity.value;
5886 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5888 t->glosstexture = r_texture_white;
5889 t->backgroundglosstexture = r_texture_white;
5890 t->specularscale = r_shadow_gloss2intensity.value;
5891 t->specularpower = r_shadow_gloss2exponent.value;
5894 t->specularscale *= t->specularscalemod;
5895 t->specularpower *= t->specularpowermod;
5897 // lightmaps mode looks bad with dlights using actual texturing, so turn
5898 // off the colormap and glossmap, but leave the normalmap on as it still
5899 // accurately represents the shading involved
5900 if (gl_lightmaps.integer)
5902 t->basetexture = r_texture_grey128;
5903 t->backgroundbasetexture = NULL;
5904 t->specularscale = 0;
5905 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5908 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5909 VectorClear(t->dlightcolor);
5910 t->currentnumlayers = 0;
5911 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5914 int blendfunc1, blendfunc2;
5916 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5918 blendfunc1 = GL_SRC_ALPHA;
5919 blendfunc2 = GL_ONE;
5921 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5923 blendfunc1 = GL_SRC_ALPHA;
5924 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5926 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5928 blendfunc1 = t->customblendfunc[0];
5929 blendfunc2 = t->customblendfunc[1];
5933 blendfunc1 = GL_ONE;
5934 blendfunc2 = GL_ZERO;
5936 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5937 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5938 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5939 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5941 // fullbright is not affected by r_refdef.lightmapintensity
5942 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]);
5943 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5944 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]);
5945 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5946 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]);
5950 vec3_t ambientcolor;
5952 // set the color tint used for lights affecting this surface
5953 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5955 // q3bsp has no lightmap updates, so the lightstylevalue that
5956 // would normally be baked into the lightmap must be
5957 // applied to the color
5958 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5959 if (model->type == mod_brushq3)
5960 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5961 colorscale *= r_refdef.lightmapintensity;
5962 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5963 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5964 // basic lit geometry
5965 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]);
5966 // add pants/shirt if needed
5967 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5968 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]);
5969 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5970 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]);
5971 // now add ambient passes if needed
5972 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5974 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]);
5975 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5976 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]);
5977 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5978 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]);
5981 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5982 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]);
5983 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5985 // if this is opaque use alpha blend which will darken the earlier
5988 // if this is an alpha blended material, all the earlier passes
5989 // were darkened by fog already, so we only need to add the fog
5990 // color ontop through the fog mask texture
5992 // if this is an additive blended material, all the earlier passes
5993 // were darkened by fog already, and we should not add fog color
5994 // (because the background was not darkened, there is no fog color
5995 // that was lost behind it).
5996 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]);
6000 return t->currentframe;
6003 rsurfacestate_t rsurface;
6005 void R_Mesh_ResizeArrays(int newvertices)
6008 if (rsurface.array_size >= newvertices)
6010 if (rsurface.array_modelvertex3f)
6011 Mem_Free(rsurface.array_modelvertex3f);
6012 rsurface.array_size = (newvertices + 1023) & ~1023;
6013 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
6014 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
6015 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
6016 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
6017 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
6018 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
6019 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
6020 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
6021 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
6022 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
6023 rsurface.array_color4f = base + rsurface.array_size * 27;
6024 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6027 void RSurf_ActiveWorldEntity(void)
6029 dp_model_t *model = r_refdef.scene.worldmodel;
6030 //if (rsurface.entity == r_refdef.scene.worldentity)
6032 rsurface.entity = r_refdef.scene.worldentity;
6033 rsurface.skeleton = NULL;
6034 rsurface.ent_skinnum = 0;
6035 rsurface.ent_qwskin = -1;
6036 rsurface.ent_shadertime = 0;
6037 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
6038 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6039 if (rsurface.array_size < model->surfmesh.num_vertices)
6040 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6041 rsurface.matrix = identitymatrix;
6042 rsurface.inversematrix = identitymatrix;
6043 rsurface.matrixscale = 1;
6044 rsurface.inversematrixscale = 1;
6045 R_Mesh_Matrix(&identitymatrix);
6046 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6047 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6048 rsurface.fograngerecip = r_refdef.fograngerecip;
6049 rsurface.fogheightfade = r_refdef.fogheightfade;
6050 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6051 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6052 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6053 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6054 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6055 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6056 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6057 VectorSet(rsurface.glowmod, 1, 1, 1);
6058 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6059 rsurface.frameblend[0].lerp = 1;
6060 rsurface.ent_alttextures = false;
6061 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6062 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6063 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6064 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6065 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6066 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6067 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6068 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6069 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6070 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6071 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6072 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6073 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6074 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6075 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6076 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6077 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6078 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6079 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6080 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6081 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6082 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6083 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6084 rsurface.modelelement3i = model->surfmesh.data_element3i;
6085 rsurface.modelelement3s = model->surfmesh.data_element3s;
6086 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6087 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6088 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6089 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6090 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6091 rsurface.modelsurfaces = model->data_surfaces;
6092 rsurface.generatedvertex = false;
6093 rsurface.vertex3f = rsurface.modelvertex3f;
6094 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6095 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6096 rsurface.svector3f = rsurface.modelsvector3f;
6097 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6098 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6099 rsurface.tvector3f = rsurface.modeltvector3f;
6100 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6101 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6102 rsurface.normal3f = rsurface.modelnormal3f;
6103 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6104 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6105 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6108 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6110 dp_model_t *model = ent->model;
6111 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6113 rsurface.entity = (entity_render_t *)ent;
6114 rsurface.skeleton = ent->skeleton;
6115 rsurface.ent_skinnum = ent->skinnum;
6116 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;
6117 rsurface.ent_shadertime = ent->shadertime;
6118 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6119 rsurface.ent_flags = ent->flags;
6120 if (rsurface.array_size < model->surfmesh.num_vertices)
6121 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6122 rsurface.matrix = ent->matrix;
6123 rsurface.inversematrix = ent->inversematrix;
6124 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6125 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6126 R_Mesh_Matrix(&rsurface.matrix);
6127 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6128 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6129 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6130 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6131 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6132 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6133 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6134 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6135 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6136 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6137 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6138 VectorCopy(ent->glowmod, rsurface.glowmod);
6139 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6140 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6141 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6142 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6143 if (ent->model->brush.submodel)
6145 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6146 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6148 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6150 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6152 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6153 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6154 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6155 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6157 else if (wanttangents)
6159 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6160 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6161 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6162 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6163 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6165 else if (wantnormals)
6167 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6168 rsurface.modelsvector3f = NULL;
6169 rsurface.modeltvector3f = NULL;
6170 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6171 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6175 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6176 rsurface.modelsvector3f = NULL;
6177 rsurface.modeltvector3f = NULL;
6178 rsurface.modelnormal3f = NULL;
6179 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6181 rsurface.modelvertex3f_bufferobject = 0;
6182 rsurface.modelvertex3f_bufferoffset = 0;
6183 rsurface.modelsvector3f_bufferobject = 0;
6184 rsurface.modelsvector3f_bufferoffset = 0;
6185 rsurface.modeltvector3f_bufferobject = 0;
6186 rsurface.modeltvector3f_bufferoffset = 0;
6187 rsurface.modelnormal3f_bufferobject = 0;
6188 rsurface.modelnormal3f_bufferoffset = 0;
6189 rsurface.generatedvertex = true;
6193 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6194 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6195 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6196 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6197 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6198 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6199 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6200 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6201 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6202 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6203 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6204 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6205 rsurface.generatedvertex = false;
6207 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6208 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6209 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6210 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6211 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6212 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6213 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6214 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6215 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6216 rsurface.modelelement3i = model->surfmesh.data_element3i;
6217 rsurface.modelelement3s = model->surfmesh.data_element3s;
6218 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6219 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6220 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6221 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6222 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6223 rsurface.modelsurfaces = model->data_surfaces;
6224 rsurface.vertex3f = rsurface.modelvertex3f;
6225 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6226 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6227 rsurface.svector3f = rsurface.modelsvector3f;
6228 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6229 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6230 rsurface.tvector3f = rsurface.modeltvector3f;
6231 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6232 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6233 rsurface.normal3f = rsurface.modelnormal3f;
6234 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6235 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6236 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6239 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)
6241 rsurface.entity = r_refdef.scene.worldentity;
6242 rsurface.skeleton = NULL;
6243 rsurface.ent_skinnum = 0;
6244 rsurface.ent_qwskin = -1;
6245 rsurface.ent_shadertime = shadertime;
6246 Vector4Set(rsurface.ent_color, r, g, b, a);
6247 rsurface.ent_flags = entflags;
6248 rsurface.modelnum_vertices = numvertices;
6249 rsurface.modelnum_triangles = numtriangles;
6250 if (rsurface.array_size < rsurface.modelnum_vertices)
6251 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6252 rsurface.matrix = *matrix;
6253 rsurface.inversematrix = *inversematrix;
6254 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6255 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6256 R_Mesh_Matrix(&rsurface.matrix);
6257 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6258 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6259 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6260 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6261 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6262 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6263 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6264 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6265 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6266 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6267 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6268 VectorSet(rsurface.glowmod, 1, 1, 1);
6269 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6270 rsurface.frameblend[0].lerp = 1;
6271 rsurface.ent_alttextures = false;
6272 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6273 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6276 rsurface.modelvertex3f = vertex3f;
6277 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6278 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6279 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6281 else if (wantnormals)
6283 rsurface.modelvertex3f = vertex3f;
6284 rsurface.modelsvector3f = NULL;
6285 rsurface.modeltvector3f = NULL;
6286 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6290 rsurface.modelvertex3f = vertex3f;
6291 rsurface.modelsvector3f = NULL;
6292 rsurface.modeltvector3f = NULL;
6293 rsurface.modelnormal3f = NULL;
6295 rsurface.modelvertex3f_bufferobject = 0;
6296 rsurface.modelvertex3f_bufferoffset = 0;
6297 rsurface.modelsvector3f_bufferobject = 0;
6298 rsurface.modelsvector3f_bufferoffset = 0;
6299 rsurface.modeltvector3f_bufferobject = 0;
6300 rsurface.modeltvector3f_bufferoffset = 0;
6301 rsurface.modelnormal3f_bufferobject = 0;
6302 rsurface.modelnormal3f_bufferoffset = 0;
6303 rsurface.generatedvertex = true;
6304 rsurface.modellightmapcolor4f = color4f;
6305 rsurface.modellightmapcolor4f_bufferobject = 0;
6306 rsurface.modellightmapcolor4f_bufferoffset = 0;
6307 rsurface.modeltexcoordtexture2f = texcoord2f;
6308 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6309 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6310 rsurface.modeltexcoordlightmap2f = NULL;
6311 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6312 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6313 rsurface.modelelement3i = element3i;
6314 rsurface.modelelement3s = element3s;
6315 rsurface.modelelement3i_bufferobject = 0;
6316 rsurface.modelelement3s_bufferobject = 0;
6317 rsurface.modellightmapoffsets = NULL;
6318 rsurface.modelsurfaces = NULL;
6319 rsurface.vertex3f = rsurface.modelvertex3f;
6320 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6321 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6322 rsurface.svector3f = rsurface.modelsvector3f;
6323 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6324 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6325 rsurface.tvector3f = rsurface.modeltvector3f;
6326 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6327 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6328 rsurface.normal3f = rsurface.modelnormal3f;
6329 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6330 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6331 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6333 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6335 if ((wantnormals || wanttangents) && !normal3f)
6336 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6337 if (wanttangents && !svector3f)
6338 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);
6342 float RSurf_FogPoint(const float *v)
6344 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6345 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6346 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6347 float FogHeightFade = r_refdef.fogheightfade;
6349 unsigned int fogmasktableindex;
6350 if (r_refdef.fogplaneviewabove)
6351 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6353 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6354 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6355 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6358 float RSurf_FogVertex(const float *v)
6360 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6361 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6362 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6363 float FogHeightFade = rsurface.fogheightfade;
6365 unsigned int fogmasktableindex;
6366 if (r_refdef.fogplaneviewabove)
6367 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6369 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6370 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6371 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6374 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6375 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6378 int texturesurfaceindex;
6383 const float *v1, *in_tc;
6385 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6387 q3shaderinfo_deform_t *deform;
6388 // 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
6389 if (rsurface.generatedvertex)
6391 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6392 generatenormals = true;
6393 for (i = 0;i < Q3MAXDEFORMS;i++)
6395 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6397 generatetangents = true;
6398 generatenormals = true;
6400 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6401 generatenormals = true;
6403 if (generatenormals && !rsurface.modelnormal3f)
6405 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6406 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6407 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6408 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6410 if (generatetangents && !rsurface.modelsvector3f)
6412 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6413 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6414 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6415 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6416 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6417 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6418 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);
6421 rsurface.vertex3f = rsurface.modelvertex3f;
6422 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6423 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6424 rsurface.svector3f = rsurface.modelsvector3f;
6425 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6426 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6427 rsurface.tvector3f = rsurface.modeltvector3f;
6428 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6429 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6430 rsurface.normal3f = rsurface.modelnormal3f;
6431 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6432 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6433 // if vertices are deformed (sprite flares and things in maps, possibly
6434 // water waves, bulges and other deformations), generate them into
6435 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6436 // (may be static model data or generated data for an animated model, or
6437 // the previous deform pass)
6438 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6440 switch (deform->deform)
6443 case Q3DEFORM_PROJECTIONSHADOW:
6444 case Q3DEFORM_TEXT0:
6445 case Q3DEFORM_TEXT1:
6446 case Q3DEFORM_TEXT2:
6447 case Q3DEFORM_TEXT3:
6448 case Q3DEFORM_TEXT4:
6449 case Q3DEFORM_TEXT5:
6450 case Q3DEFORM_TEXT6:
6451 case Q3DEFORM_TEXT7:
6454 case Q3DEFORM_AUTOSPRITE:
6455 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6456 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6457 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6458 VectorNormalize(newforward);
6459 VectorNormalize(newright);
6460 VectorNormalize(newup);
6461 // make deformed versions of only the model vertices used by the specified surfaces
6462 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6464 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6465 // a single autosprite surface can contain multiple sprites...
6466 for (j = 0;j < surface->num_vertices - 3;j += 4)
6468 VectorClear(center);
6469 for (i = 0;i < 4;i++)
6470 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6471 VectorScale(center, 0.25f, center);
6472 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6473 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6474 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6475 for (i = 0;i < 4;i++)
6477 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6478 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6481 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);
6482 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);
6484 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6485 rsurface.vertex3f_bufferobject = 0;
6486 rsurface.vertex3f_bufferoffset = 0;
6487 rsurface.svector3f = rsurface.array_deformedsvector3f;
6488 rsurface.svector3f_bufferobject = 0;
6489 rsurface.svector3f_bufferoffset = 0;
6490 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6491 rsurface.tvector3f_bufferobject = 0;
6492 rsurface.tvector3f_bufferoffset = 0;
6493 rsurface.normal3f = rsurface.array_deformednormal3f;
6494 rsurface.normal3f_bufferobject = 0;
6495 rsurface.normal3f_bufferoffset = 0;
6497 case Q3DEFORM_AUTOSPRITE2:
6498 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6499 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6500 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6501 VectorNormalize(newforward);
6502 VectorNormalize(newright);
6503 VectorNormalize(newup);
6504 // make deformed versions of only the model vertices used by the specified surfaces
6505 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6507 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6508 const float *v1, *v2;
6518 memset(shortest, 0, sizeof(shortest));
6519 // a single autosprite surface can contain multiple sprites...
6520 for (j = 0;j < surface->num_vertices - 3;j += 4)
6522 VectorClear(center);
6523 for (i = 0;i < 4;i++)
6524 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6525 VectorScale(center, 0.25f, center);
6526 // find the two shortest edges, then use them to define the
6527 // axis vectors for rotating around the central axis
6528 for (i = 0;i < 6;i++)
6530 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6531 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6533 Debug_PolygonBegin(NULL, 0);
6534 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6535 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);
6536 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6539 l = VectorDistance2(v1, v2);
6540 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6542 l += (1.0f / 1024.0f);
6543 if (shortest[0].length2 > l || i == 0)
6545 shortest[1] = shortest[0];
6546 shortest[0].length2 = l;
6547 shortest[0].v1 = v1;
6548 shortest[0].v2 = v2;
6550 else if (shortest[1].length2 > l || i == 1)
6552 shortest[1].length2 = l;
6553 shortest[1].v1 = v1;
6554 shortest[1].v2 = v2;
6557 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6558 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6560 Debug_PolygonBegin(NULL, 0);
6561 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6562 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);
6563 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6566 // this calculates the right vector from the shortest edge
6567 // and the up vector from the edge midpoints
6568 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6569 VectorNormalize(right);
6570 VectorSubtract(end, start, up);
6571 VectorNormalize(up);
6572 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6573 VectorSubtract(rsurface.localvieworigin, center, forward);
6574 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6575 VectorNegate(forward, forward);
6576 VectorReflect(forward, 0, up, forward);
6577 VectorNormalize(forward);
6578 CrossProduct(up, forward, newright);
6579 VectorNormalize(newright);
6581 Debug_PolygonBegin(NULL, 0);
6582 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);
6583 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6584 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6588 Debug_PolygonBegin(NULL, 0);
6589 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6590 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6591 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6594 // rotate the quad around the up axis vector, this is made
6595 // especially easy by the fact we know the quad is flat,
6596 // so we only have to subtract the center position and
6597 // measure distance along the right vector, and then
6598 // multiply that by the newright vector and add back the
6600 // we also need to subtract the old position to undo the
6601 // displacement from the center, which we do with a
6602 // DotProduct, the subtraction/addition of center is also
6603 // optimized into DotProducts here
6604 l = DotProduct(right, center);
6605 for (i = 0;i < 4;i++)
6607 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6608 f = DotProduct(right, v1) - l;
6609 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6612 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);
6613 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);
6615 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6616 rsurface.vertex3f_bufferobject = 0;
6617 rsurface.vertex3f_bufferoffset = 0;
6618 rsurface.svector3f = rsurface.array_deformedsvector3f;
6619 rsurface.svector3f_bufferobject = 0;
6620 rsurface.svector3f_bufferoffset = 0;
6621 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6622 rsurface.tvector3f_bufferobject = 0;
6623 rsurface.tvector3f_bufferoffset = 0;
6624 rsurface.normal3f = rsurface.array_deformednormal3f;
6625 rsurface.normal3f_bufferobject = 0;
6626 rsurface.normal3f_bufferoffset = 0;
6628 case Q3DEFORM_NORMAL:
6629 // deform the normals to make reflections wavey
6630 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6632 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6633 for (j = 0;j < surface->num_vertices;j++)
6636 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6637 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6638 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6639 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6640 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6641 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6642 VectorNormalize(normal);
6644 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);
6646 rsurface.svector3f = rsurface.array_deformedsvector3f;
6647 rsurface.svector3f_bufferobject = 0;
6648 rsurface.svector3f_bufferoffset = 0;
6649 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6650 rsurface.tvector3f_bufferobject = 0;
6651 rsurface.tvector3f_bufferoffset = 0;
6652 rsurface.normal3f = rsurface.array_deformednormal3f;
6653 rsurface.normal3f_bufferobject = 0;
6654 rsurface.normal3f_bufferoffset = 0;
6657 // deform vertex array to make wavey water and flags and such
6658 waveparms[0] = deform->waveparms[0];
6659 waveparms[1] = deform->waveparms[1];
6660 waveparms[2] = deform->waveparms[2];
6661 waveparms[3] = deform->waveparms[3];
6662 // this is how a divisor of vertex influence on deformation
6663 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6664 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6665 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6667 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6668 for (j = 0;j < surface->num_vertices;j++)
6670 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6671 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6672 // if the wavefunc depends on time, evaluate it per-vertex
6675 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6676 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6678 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6681 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6682 rsurface.vertex3f_bufferobject = 0;
6683 rsurface.vertex3f_bufferoffset = 0;
6685 case Q3DEFORM_BULGE:
6686 // deform vertex array to make the surface have moving bulges
6687 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6689 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6690 for (j = 0;j < surface->num_vertices;j++)
6692 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6693 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6696 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6697 rsurface.vertex3f_bufferobject = 0;
6698 rsurface.vertex3f_bufferoffset = 0;
6701 // deform vertex array
6702 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6703 VectorScale(deform->parms, scale, waveparms);
6704 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6706 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6707 for (j = 0;j < surface->num_vertices;j++)
6708 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6710 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6711 rsurface.vertex3f_bufferobject = 0;
6712 rsurface.vertex3f_bufferoffset = 0;
6716 // generate texcoords based on the chosen texcoord source
6717 switch(rsurface.texture->tcgen.tcgen)
6720 case Q3TCGEN_TEXTURE:
6721 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6722 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6723 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6725 case Q3TCGEN_LIGHTMAP:
6726 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6727 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6728 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6730 case Q3TCGEN_VECTOR:
6731 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6733 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6734 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)
6736 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6737 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6740 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6741 rsurface.texcoordtexture2f_bufferobject = 0;
6742 rsurface.texcoordtexture2f_bufferoffset = 0;
6744 case Q3TCGEN_ENVIRONMENT:
6745 // make environment reflections using a spheremap
6746 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6748 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6749 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6750 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6751 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6752 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6754 // identical to Q3A's method, but executed in worldspace so
6755 // carried models can be shiny too
6757 float viewer[3], d, reflected[3], worldreflected[3];
6759 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6760 // VectorNormalize(viewer);
6762 d = DotProduct(normal, viewer);
6764 reflected[0] = normal[0]*2*d - viewer[0];
6765 reflected[1] = normal[1]*2*d - viewer[1];
6766 reflected[2] = normal[2]*2*d - viewer[2];
6767 // note: this is proportinal to viewer, so we can normalize later
6769 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6770 VectorNormalize(worldreflected);
6772 // note: this sphere map only uses world x and z!
6773 // so positive and negative y will LOOK THE SAME.
6774 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6775 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6778 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6779 rsurface.texcoordtexture2f_bufferobject = 0;
6780 rsurface.texcoordtexture2f_bufferoffset = 0;
6783 // the only tcmod that needs software vertex processing is turbulent, so
6784 // check for it here and apply the changes if needed
6785 // and we only support that as the first one
6786 // (handling a mixture of turbulent and other tcmods would be problematic
6787 // without punting it entirely to a software path)
6788 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6790 amplitude = rsurface.texture->tcmods[0].parms[1];
6791 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6792 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6794 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6795 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)
6797 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6798 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6801 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6802 rsurface.texcoordtexture2f_bufferobject = 0;
6803 rsurface.texcoordtexture2f_bufferoffset = 0;
6805 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6806 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6807 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6808 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6811 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6814 const msurface_t *surface = texturesurfacelist[0];
6815 const msurface_t *surface2;
6820 // TODO: lock all array ranges before render, rather than on each surface
6821 if (texturenumsurfaces == 1)
6823 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6824 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);
6826 else if (r_batchmode.integer == 2)
6828 #define MAXBATCHTRIANGLES 4096
6829 int batchtriangles = 0;
6830 int batchelements[MAXBATCHTRIANGLES*3];
6831 for (i = 0;i < texturenumsurfaces;i = j)
6833 surface = texturesurfacelist[i];
6835 if (surface->num_triangles > MAXBATCHTRIANGLES)
6837 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);
6840 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6841 batchtriangles = surface->num_triangles;
6842 firstvertex = surface->num_firstvertex;
6843 endvertex = surface->num_firstvertex + surface->num_vertices;
6844 for (;j < texturenumsurfaces;j++)
6846 surface2 = texturesurfacelist[j];
6847 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6849 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6850 batchtriangles += surface2->num_triangles;
6851 firstvertex = min(firstvertex, surface2->num_firstvertex);
6852 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6854 surface2 = texturesurfacelist[j-1];
6855 numvertices = endvertex - firstvertex;
6856 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6859 else if (r_batchmode.integer == 1)
6861 for (i = 0;i < texturenumsurfaces;i = j)
6863 surface = texturesurfacelist[i];
6864 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6865 if (texturesurfacelist[j] != surface2)
6867 surface2 = texturesurfacelist[j-1];
6868 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6869 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6870 GL_LockArrays(surface->num_firstvertex, numvertices);
6871 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6876 for (i = 0;i < texturenumsurfaces;i++)
6878 surface = texturesurfacelist[i];
6879 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6880 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);
6885 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6887 int i, planeindex, vertexindex;
6891 r_waterstate_waterplane_t *p, *bestp;
6892 const msurface_t *surface;
6893 if (r_waterstate.renderingscene)
6895 for (i = 0;i < texturenumsurfaces;i++)
6897 surface = texturesurfacelist[i];
6898 if (lightmaptexunit >= 0)
6899 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6900 if (deluxemaptexunit >= 0)
6901 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6902 // pick the closest matching water plane
6905 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6908 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6910 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6911 d += fabs(PlaneDiff(vert, &p->plane));
6913 if (bestd > d || !bestp)
6921 if (refractiontexunit >= 0)
6922 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6923 if (reflectiontexunit >= 0)
6924 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6928 if (refractiontexunit >= 0)
6929 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6930 if (reflectiontexunit >= 0)
6931 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6933 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6934 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);
6938 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6942 const msurface_t *surface = texturesurfacelist[0];
6943 const msurface_t *surface2;
6948 // TODO: lock all array ranges before render, rather than on each surface
6949 if (texturenumsurfaces == 1)
6951 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6952 if (deluxemaptexunit >= 0)
6953 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6954 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6955 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);
6957 else if (r_batchmode.integer == 2)
6959 #define MAXBATCHTRIANGLES 4096
6960 int batchtriangles = 0;
6961 int batchelements[MAXBATCHTRIANGLES*3];
6962 for (i = 0;i < texturenumsurfaces;i = j)
6964 surface = texturesurfacelist[i];
6965 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6966 if (deluxemaptexunit >= 0)
6967 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6969 if (surface->num_triangles > MAXBATCHTRIANGLES)
6971 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);
6974 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6975 batchtriangles = surface->num_triangles;
6976 firstvertex = surface->num_firstvertex;
6977 endvertex = surface->num_firstvertex + surface->num_vertices;
6978 for (;j < texturenumsurfaces;j++)
6980 surface2 = texturesurfacelist[j];
6981 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6983 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6984 batchtriangles += surface2->num_triangles;
6985 firstvertex = min(firstvertex, surface2->num_firstvertex);
6986 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6988 surface2 = texturesurfacelist[j-1];
6989 numvertices = endvertex - firstvertex;
6990 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6993 else if (r_batchmode.integer == 1)
6996 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6997 for (i = 0;i < texturenumsurfaces;i = j)
6999 surface = texturesurfacelist[i];
7000 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7001 if (texturesurfacelist[j] != surface2)
7003 Con_Printf(" %i", j - i);
7006 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
7008 for (i = 0;i < texturenumsurfaces;i = j)
7010 surface = texturesurfacelist[i];
7011 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7012 if (deluxemaptexunit >= 0)
7013 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7014 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7015 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
7018 Con_Printf(" %i", j - i);
7020 surface2 = texturesurfacelist[j-1];
7021 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7022 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7023 GL_LockArrays(surface->num_firstvertex, numvertices);
7024 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7032 for (i = 0;i < texturenumsurfaces;i++)
7034 surface = texturesurfacelist[i];
7035 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7036 if (deluxemaptexunit >= 0)
7037 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7038 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7039 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);
7044 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7047 int texturesurfaceindex;
7048 if (r_showsurfaces.integer == 2)
7050 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7052 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7053 for (j = 0;j < surface->num_triangles;j++)
7055 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7056 GL_Color(f, f, f, 1);
7057 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7063 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7065 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7066 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7067 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);
7068 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7069 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);
7074 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7076 int texturesurfaceindex;
7080 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7082 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7083 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)
7091 rsurface.lightmapcolor4f = rsurface.array_color4f;
7092 rsurface.lightmapcolor4f_bufferobject = 0;
7093 rsurface.lightmapcolor4f_bufferoffset = 0;
7096 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7098 int texturesurfaceindex;
7104 if (rsurface.lightmapcolor4f)
7106 // generate color arrays for the surfaces in this list
7107 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7109 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7110 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)
7112 f = RSurf_FogVertex(v);
7122 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7124 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7125 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)
7127 f = RSurf_FogVertex(v);
7135 rsurface.lightmapcolor4f = rsurface.array_color4f;
7136 rsurface.lightmapcolor4f_bufferobject = 0;
7137 rsurface.lightmapcolor4f_bufferoffset = 0;
7140 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7142 int texturesurfaceindex;
7148 if (!rsurface.lightmapcolor4f)
7150 // generate color arrays for the surfaces in this list
7151 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7153 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7154 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)
7156 f = RSurf_FogVertex(v);
7157 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7158 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7159 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7163 rsurface.lightmapcolor4f = rsurface.array_color4f;
7164 rsurface.lightmapcolor4f_bufferobject = 0;
7165 rsurface.lightmapcolor4f_bufferoffset = 0;
7168 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7170 int texturesurfaceindex;
7174 if (!rsurface.lightmapcolor4f)
7176 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7178 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7179 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)
7187 rsurface.lightmapcolor4f = rsurface.array_color4f;
7188 rsurface.lightmapcolor4f_bufferobject = 0;
7189 rsurface.lightmapcolor4f_bufferoffset = 0;
7192 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7194 int texturesurfaceindex;
7198 if (!rsurface.lightmapcolor4f)
7200 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7202 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7203 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)
7205 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7206 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7207 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7211 rsurface.lightmapcolor4f = rsurface.array_color4f;
7212 rsurface.lightmapcolor4f_bufferobject = 0;
7213 rsurface.lightmapcolor4f_bufferoffset = 0;
7216 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7219 rsurface.lightmapcolor4f = NULL;
7220 rsurface.lightmapcolor4f_bufferobject = 0;
7221 rsurface.lightmapcolor4f_bufferoffset = 0;
7222 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7223 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7224 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7225 GL_Color(r, g, b, a);
7226 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7229 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7231 // TODO: optimize applyfog && applycolor case
7232 // just apply fog if necessary, and tint the fog color array if necessary
7233 rsurface.lightmapcolor4f = NULL;
7234 rsurface.lightmapcolor4f_bufferobject = 0;
7235 rsurface.lightmapcolor4f_bufferoffset = 0;
7236 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7237 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7238 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7239 GL_Color(r, g, b, a);
7240 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7243 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7245 int texturesurfaceindex;
7249 if (texturesurfacelist[0]->lightmapinfo)
7251 // generate color arrays for the surfaces in this list
7252 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7254 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7255 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7257 if (surface->lightmapinfo->samples)
7259 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7260 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7261 VectorScale(lm, scale, c);
7262 if (surface->lightmapinfo->styles[1] != 255)
7264 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7266 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7267 VectorMA(c, scale, lm, c);
7268 if (surface->lightmapinfo->styles[2] != 255)
7271 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7272 VectorMA(c, scale, lm, c);
7273 if (surface->lightmapinfo->styles[3] != 255)
7276 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7277 VectorMA(c, scale, lm, c);
7287 rsurface.lightmapcolor4f = rsurface.array_color4f;
7288 rsurface.lightmapcolor4f_bufferobject = 0;
7289 rsurface.lightmapcolor4f_bufferoffset = 0;
7293 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7294 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7295 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7297 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7298 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7299 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7300 GL_Color(r, g, b, a);
7301 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7304 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7306 int texturesurfaceindex;
7313 vec3_t ambientcolor;
7314 vec3_t diffusecolor;
7318 VectorCopy(rsurface.modellight_lightdir, lightdir);
7319 f = 0.5f * r_refdef.lightmapintensity;
7320 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7321 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7322 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7323 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7324 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7325 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7327 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7329 // generate color arrays for the surfaces in this list
7330 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7332 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7333 int numverts = surface->num_vertices;
7334 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7335 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7336 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7337 // q3-style directional shading
7338 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7340 if ((f = DotProduct(n, lightdir)) > 0)
7341 VectorMA(ambientcolor, f, diffusecolor, c);
7343 VectorCopy(ambientcolor, c);
7351 rsurface.lightmapcolor4f = rsurface.array_color4f;
7352 rsurface.lightmapcolor4f_bufferobject = 0;
7353 rsurface.lightmapcolor4f_bufferoffset = 0;
7354 *applycolor = false;
7358 *r = ambientcolor[0];
7359 *g = ambientcolor[1];
7360 *b = ambientcolor[2];
7361 rsurface.lightmapcolor4f = NULL;
7362 rsurface.lightmapcolor4f_bufferobject = 0;
7363 rsurface.lightmapcolor4f_bufferoffset = 0;
7367 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7369 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7370 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7371 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7372 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7373 GL_Color(r, g, b, a);
7374 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7377 void RSurf_SetupDepthAndCulling(void)
7379 // submodels are biased to avoid z-fighting with world surfaces that they
7380 // may be exactly overlapping (avoids z-fighting artifacts on certain
7381 // doors and things in Quake maps)
7382 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7383 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7384 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7385 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7388 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7390 // transparent sky would be ridiculous
7391 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7393 R_SetupGenericShader(false);
7394 skyrenderlater = true;
7395 RSurf_SetupDepthAndCulling();
7397 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7398 // skymasking on them, and Quake3 never did sky masking (unlike
7399 // software Quake and software Quake2), so disable the sky masking
7400 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7401 // and skymasking also looks very bad when noclipping outside the
7402 // level, so don't use it then either.
7403 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7405 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7406 R_Mesh_ColorPointer(NULL, 0, 0);
7407 R_Mesh_ResetTextureState();
7408 if (skyrendermasked)
7410 R_SetupDepthOrShadowShader();
7411 // depth-only (masking)
7412 GL_ColorMask(0,0,0,0);
7413 // just to make sure that braindead drivers don't draw
7414 // anything despite that colormask...
7415 GL_BlendFunc(GL_ZERO, GL_ONE);
7419 R_SetupGenericShader(false);
7421 GL_BlendFunc(GL_ONE, GL_ZERO);
7423 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7424 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7425 if (skyrendermasked)
7426 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7428 R_Mesh_ResetTextureState();
7429 GL_Color(1, 1, 1, 1);
7432 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7434 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7437 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7438 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7439 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7440 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7441 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7442 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7443 if (rsurface.texture->backgroundcurrentskinframe)
7445 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7446 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7447 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7448 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7450 if(rsurface.texture->colormapping)
7452 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7453 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7455 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7456 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7457 R_Mesh_ColorPointer(NULL, 0, 0);
7459 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7461 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7463 // render background
7464 GL_BlendFunc(GL_ONE, GL_ZERO);
7466 GL_AlphaTest(false);
7468 GL_Color(1, 1, 1, 1);
7469 R_Mesh_ColorPointer(NULL, 0, 0);
7471 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7472 if (r_glsl_permutation)
7474 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7475 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7476 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7477 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7478 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7479 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7480 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);
7482 GL_LockArrays(0, 0);
7484 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7485 GL_DepthMask(false);
7486 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7487 R_Mesh_ColorPointer(NULL, 0, 0);
7489 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7490 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7491 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7494 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7495 if (!r_glsl_permutation)
7498 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7499 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7500 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7501 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7502 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7503 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7505 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7507 GL_BlendFunc(GL_ONE, GL_ZERO);
7509 GL_AlphaTest(false);
7513 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7514 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7515 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7518 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7520 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7521 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);
7523 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7527 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7528 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);
7530 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7532 GL_LockArrays(0, 0);
7535 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7537 // OpenGL 1.3 path - anything not completely ancient
7538 int texturesurfaceindex;
7539 qboolean applycolor;
7543 const texturelayer_t *layer;
7544 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7546 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7549 int layertexrgbscale;
7550 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7552 if (layerindex == 0)
7556 GL_AlphaTest(false);
7557 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7560 GL_DepthMask(layer->depthmask && writedepth);
7561 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7562 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7564 layertexrgbscale = 4;
7565 VectorScale(layer->color, 0.25f, layercolor);
7567 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7569 layertexrgbscale = 2;
7570 VectorScale(layer->color, 0.5f, layercolor);
7574 layertexrgbscale = 1;
7575 VectorScale(layer->color, 1.0f, layercolor);
7577 layercolor[3] = layer->color[3];
7578 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7579 R_Mesh_ColorPointer(NULL, 0, 0);
7580 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7581 switch (layer->type)
7583 case TEXTURELAYERTYPE_LITTEXTURE:
7584 memset(&m, 0, sizeof(m));
7585 m.tex[0] = R_GetTexture(r_texture_white);
7586 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7587 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7588 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7589 m.tex[1] = R_GetTexture(layer->texture);
7590 m.texmatrix[1] = layer->texmatrix;
7591 m.texrgbscale[1] = layertexrgbscale;
7592 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7593 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7594 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7595 R_Mesh_TextureState(&m);
7596 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7597 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7598 else if (rsurface.uselightmaptexture)
7599 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7601 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7603 case TEXTURELAYERTYPE_TEXTURE:
7604 memset(&m, 0, sizeof(m));
7605 m.tex[0] = R_GetTexture(layer->texture);
7606 m.texmatrix[0] = layer->texmatrix;
7607 m.texrgbscale[0] = layertexrgbscale;
7608 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7609 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7610 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7611 R_Mesh_TextureState(&m);
7612 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7614 case TEXTURELAYERTYPE_FOG:
7615 memset(&m, 0, sizeof(m));
7616 m.texrgbscale[0] = layertexrgbscale;
7619 m.tex[0] = R_GetTexture(layer->texture);
7620 m.texmatrix[0] = layer->texmatrix;
7621 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7622 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7623 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7625 R_Mesh_TextureState(&m);
7626 // generate a color array for the fog pass
7627 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7628 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7634 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7635 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)
7637 f = 1 - RSurf_FogVertex(v);
7638 c[0] = layercolor[0];
7639 c[1] = layercolor[1];
7640 c[2] = layercolor[2];
7641 c[3] = f * layercolor[3];
7644 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7647 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7649 GL_LockArrays(0, 0);
7652 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7654 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7655 GL_AlphaTest(false);
7659 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7661 // OpenGL 1.1 - crusty old voodoo path
7662 int texturesurfaceindex;
7666 const texturelayer_t *layer;
7667 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7669 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7671 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7673 if (layerindex == 0)
7677 GL_AlphaTest(false);
7678 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7681 GL_DepthMask(layer->depthmask && writedepth);
7682 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7683 R_Mesh_ColorPointer(NULL, 0, 0);
7684 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7685 switch (layer->type)
7687 case TEXTURELAYERTYPE_LITTEXTURE:
7688 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7690 // two-pass lit texture with 2x rgbscale
7691 // first the lightmap pass
7692 memset(&m, 0, sizeof(m));
7693 m.tex[0] = R_GetTexture(r_texture_white);
7694 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7695 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7696 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7697 R_Mesh_TextureState(&m);
7698 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7699 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7700 else if (rsurface.uselightmaptexture)
7701 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7703 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7704 GL_LockArrays(0, 0);
7705 // then apply the texture to it
7706 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7707 memset(&m, 0, sizeof(m));
7708 m.tex[0] = R_GetTexture(layer->texture);
7709 m.texmatrix[0] = layer->texmatrix;
7710 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7711 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7712 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7713 R_Mesh_TextureState(&m);
7714 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);
7718 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7719 memset(&m, 0, sizeof(m));
7720 m.tex[0] = R_GetTexture(layer->texture);
7721 m.texmatrix[0] = layer->texmatrix;
7722 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7723 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7724 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7725 R_Mesh_TextureState(&m);
7726 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7727 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);
7729 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);
7732 case TEXTURELAYERTYPE_TEXTURE:
7733 // singletexture unlit texture with transparency support
7734 memset(&m, 0, sizeof(m));
7735 m.tex[0] = R_GetTexture(layer->texture);
7736 m.texmatrix[0] = layer->texmatrix;
7737 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7738 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7739 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7740 R_Mesh_TextureState(&m);
7741 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);
7743 case TEXTURELAYERTYPE_FOG:
7744 // singletexture fogging
7745 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7748 memset(&m, 0, sizeof(m));
7749 m.tex[0] = R_GetTexture(layer->texture);
7750 m.texmatrix[0] = layer->texmatrix;
7751 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7752 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7753 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7754 R_Mesh_TextureState(&m);
7757 R_Mesh_ResetTextureState();
7758 // generate a color array for the fog pass
7759 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7765 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7766 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)
7768 f = 1 - RSurf_FogVertex(v);
7769 c[0] = layer->color[0];
7770 c[1] = layer->color[1];
7771 c[2] = layer->color[2];
7772 c[3] = f * layer->color[3];
7775 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7778 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7780 GL_LockArrays(0, 0);
7783 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7785 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7786 GL_AlphaTest(false);
7790 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7794 GL_AlphaTest(false);
7795 R_Mesh_ColorPointer(NULL, 0, 0);
7796 R_Mesh_ResetTextureState();
7797 R_SetupGenericShader(false);
7799 if(rsurface.texture && rsurface.texture->currentskinframe)
7801 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7802 c[3] *= rsurface.texture->currentalpha;
7812 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7814 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7815 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7816 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7819 // brighten it up (as texture value 127 means "unlit")
7820 c[0] *= 2 * r_refdef.view.colorscale;
7821 c[1] *= 2 * r_refdef.view.colorscale;
7822 c[2] *= 2 * r_refdef.view.colorscale;
7824 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7825 c[3] *= r_wateralpha.value;
7827 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7829 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7830 GL_DepthMask(false);
7832 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7834 GL_BlendFunc(GL_ONE, GL_ONE);
7835 GL_DepthMask(false);
7837 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7839 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7840 GL_DepthMask(false);
7842 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7844 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7845 GL_DepthMask(false);
7849 GL_BlendFunc(GL_ONE, GL_ZERO);
7850 GL_DepthMask(writedepth);
7853 rsurface.lightmapcolor4f = NULL;
7855 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7857 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7859 rsurface.lightmapcolor4f = NULL;
7860 rsurface.lightmapcolor4f_bufferobject = 0;
7861 rsurface.lightmapcolor4f_bufferoffset = 0;
7863 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7865 qboolean applycolor = true;
7868 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7870 r_refdef.lightmapintensity = 1;
7871 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7872 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7876 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7878 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7879 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7880 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7883 if(!rsurface.lightmapcolor4f)
7884 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7886 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7887 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7888 if(r_refdef.fogenabled)
7889 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7891 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7892 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7895 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7898 RSurf_SetupDepthAndCulling();
7899 if (r_showsurfaces.integer == 3)
7900 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7901 else if (r_glsl.integer && vid.support.arb_fragment_shader)
7902 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7903 else if (gl_combine.integer && r_textureunits.integer >= 2)
7904 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7906 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7910 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7913 RSurf_SetupDepthAndCulling();
7914 if (r_showsurfaces.integer == 3)
7915 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7916 else if (r_glsl.integer && vid.support.arb_fragment_shader)
7917 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7918 else if (gl_combine.integer && r_textureunits.integer >= 2)
7919 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7921 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7925 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7928 int texturenumsurfaces, endsurface;
7930 const msurface_t *surface;
7931 const msurface_t *texturesurfacelist[1024];
7933 // if the model is static it doesn't matter what value we give for
7934 // wantnormals and wanttangents, so this logic uses only rules applicable
7935 // to a model, knowing that they are meaningless otherwise
7936 if (ent == r_refdef.scene.worldentity)
7937 RSurf_ActiveWorldEntity();
7938 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7939 RSurf_ActiveModelEntity(ent, false, false);
7941 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && vid.support.arb_fragment_shader);
7943 for (i = 0;i < numsurfaces;i = j)
7946 surface = rsurface.modelsurfaces + surfacelist[i];
7947 texture = surface->texture;
7948 rsurface.texture = R_GetCurrentTexture(texture);
7949 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7950 // scan ahead until we find a different texture
7951 endsurface = min(i + 1024, numsurfaces);
7952 texturenumsurfaces = 0;
7953 texturesurfacelist[texturenumsurfaces++] = surface;
7954 for (;j < endsurface;j++)
7956 surface = rsurface.modelsurfaces + surfacelist[j];
7957 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7959 texturesurfacelist[texturenumsurfaces++] = surface;
7961 // render the range of surfaces
7962 if (ent == r_refdef.scene.worldentity)
7963 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7965 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7967 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7968 GL_AlphaTest(false);
7971 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7973 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7977 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7979 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7981 RSurf_SetupDepthAndCulling();
7982 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7983 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7985 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7987 RSurf_SetupDepthAndCulling();
7988 GL_AlphaTest(false);
7989 R_Mesh_ColorPointer(NULL, 0, 0);
7990 R_Mesh_ResetTextureState();
7991 R_SetupGenericShader(false);
7992 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7994 GL_BlendFunc(GL_ONE, GL_ZERO);
7995 GL_Color(0, 0, 0, 1);
7996 GL_DepthTest(writedepth);
7997 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7999 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8001 RSurf_SetupDepthAndCulling();
8002 GL_AlphaTest(false);
8003 R_Mesh_ColorPointer(NULL, 0, 0);
8004 R_Mesh_ResetTextureState();
8005 R_SetupGenericShader(false);
8006 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8008 GL_BlendFunc(GL_ONE, GL_ZERO);
8010 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8012 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8013 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8014 else if (!rsurface.texture->currentnumlayers)
8016 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8018 // transparent surfaces get pushed off into the transparent queue
8019 int surfacelistindex;
8020 const msurface_t *surface;
8021 vec3_t tempcenter, center;
8022 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8024 surface = texturesurfacelist[surfacelistindex];
8025 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8026 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8027 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8028 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8029 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8034 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8035 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8040 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8044 // break the surface list down into batches by texture and use of lightmapping
8045 for (i = 0;i < numsurfaces;i = j)
8048 // texture is the base texture pointer, rsurface.texture is the
8049 // current frame/skin the texture is directing us to use (for example
8050 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8051 // use skin 1 instead)
8052 texture = surfacelist[i]->texture;
8053 rsurface.texture = R_GetCurrentTexture(texture);
8054 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8055 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8057 // if this texture is not the kind we want, skip ahead to the next one
8058 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8062 // simply scan ahead until we find a different texture or lightmap state
8063 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8065 // render the range of surfaces
8066 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
8070 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
8075 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8077 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8079 RSurf_SetupDepthAndCulling();
8080 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8081 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8083 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8085 RSurf_SetupDepthAndCulling();
8086 GL_AlphaTest(false);
8087 R_Mesh_ColorPointer(NULL, 0, 0);
8088 R_Mesh_ResetTextureState();
8089 R_SetupGenericShader(false);
8090 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8092 GL_BlendFunc(GL_ONE, GL_ZERO);
8093 GL_Color(0, 0, 0, 1);
8094 GL_DepthTest(writedepth);
8095 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8097 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8099 RSurf_SetupDepthAndCulling();
8100 GL_AlphaTest(false);
8101 R_Mesh_ColorPointer(NULL, 0, 0);
8102 R_Mesh_ResetTextureState();
8103 R_SetupGenericShader(false);
8104 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8106 GL_BlendFunc(GL_ONE, GL_ZERO);
8108 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8110 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8111 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8112 else if (!rsurface.texture->currentnumlayers)
8114 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8116 // transparent surfaces get pushed off into the transparent queue
8117 int surfacelistindex;
8118 const msurface_t *surface;
8119 vec3_t tempcenter, center;
8120 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8122 surface = texturesurfacelist[surfacelistindex];
8123 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8124 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8125 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8126 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8127 if (queueentity->transparent_offset) // transparent offset
8129 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8130 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8131 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8133 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8138 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8139 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8144 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8148 // break the surface list down into batches by texture and use of lightmapping
8149 for (i = 0;i < numsurfaces;i = j)
8152 // texture is the base texture pointer, rsurface.texture is the
8153 // current frame/skin the texture is directing us to use (for example
8154 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8155 // use skin 1 instead)
8156 texture = surfacelist[i]->texture;
8157 rsurface.texture = R_GetCurrentTexture(texture);
8158 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8159 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8161 // if this texture is not the kind we want, skip ahead to the next one
8162 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8166 // simply scan ahead until we find a different texture or lightmap state
8167 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8169 // render the range of surfaces
8170 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8174 float locboxvertex3f[6*4*3] =
8176 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8177 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8178 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8179 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8180 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8181 1,0,0, 0,0,0, 0,1,0, 1,1,0
8184 unsigned short locboxelements[6*2*3] =
8194 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8197 cl_locnode_t *loc = (cl_locnode_t *)ent;
8199 float vertex3f[6*4*3];
8201 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8202 GL_DepthMask(false);
8203 GL_DepthRange(0, 1);
8204 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8206 GL_CullFace(GL_NONE);
8207 R_Mesh_Matrix(&identitymatrix);
8209 R_Mesh_VertexPointer(vertex3f, 0, 0);
8210 R_Mesh_ColorPointer(NULL, 0, 0);
8211 R_Mesh_ResetTextureState();
8212 R_SetupGenericShader(false);
8215 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8216 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8217 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8218 surfacelist[0] < 0 ? 0.5f : 0.125f);
8220 if (VectorCompare(loc->mins, loc->maxs))
8222 VectorSet(size, 2, 2, 2);
8223 VectorMA(loc->mins, -0.5f, size, mins);
8227 VectorCopy(loc->mins, mins);
8228 VectorSubtract(loc->maxs, loc->mins, size);
8231 for (i = 0;i < 6*4*3;)
8232 for (j = 0;j < 3;j++, i++)
8233 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8235 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8238 void R_DrawLocs(void)
8241 cl_locnode_t *loc, *nearestloc;
8243 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8244 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8246 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8247 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8251 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8253 if (decalsystem->decals)
8254 Mem_Free(decalsystem->decals);
8255 memset(decalsystem, 0, sizeof(*decalsystem));
8258 static 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, int surfaceindex, int decalsequence)
8265 // expand or initialize the system
8266 if (decalsystem->maxdecals <= decalsystem->numdecals)
8268 decalsystem_t old = *decalsystem;
8269 qboolean useshortelements;
8270 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8271 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8272 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)));
8273 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8274 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8275 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8276 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8277 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8278 if (decalsystem->numdecals)
8279 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8281 Mem_Free(old.decals);
8282 for (i = 0;i < decalsystem->maxdecals*3;i++)
8283 decalsystem->element3i[i] = i;
8284 if (useshortelements)
8285 for (i = 0;i < decalsystem->maxdecals*3;i++)
8286 decalsystem->element3s[i] = i;
8289 // grab a decal and search for another free slot for the next one
8290 maxdecals = decalsystem->maxdecals;
8291 decals = decalsystem->decals;
8292 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8293 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8295 decalsystem->freedecal = i;
8296 if (decalsystem->numdecals <= i)
8297 decalsystem->numdecals = i + 1;
8299 // initialize the decal
8301 decal->triangleindex = triangleindex;
8302 decal->surfaceindex = surfaceindex;
8303 decal->decalsequence = decalsequence;
8304 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8305 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8306 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8307 decal->color4ub[0][3] = 255;
8308 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8309 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8310 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8311 decal->color4ub[1][3] = 255;
8312 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8313 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8314 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8315 decal->color4ub[2][3] = 255;
8316 decal->vertex3f[0][0] = v0[0];
8317 decal->vertex3f[0][1] = v0[1];
8318 decal->vertex3f[0][2] = v0[2];
8319 decal->vertex3f[1][0] = v1[0];
8320 decal->vertex3f[1][1] = v1[1];
8321 decal->vertex3f[1][2] = v1[2];
8322 decal->vertex3f[2][0] = v2[0];
8323 decal->vertex3f[2][1] = v2[1];
8324 decal->vertex3f[2][2] = v2[2];
8325 decal->texcoord2f[0][0] = t0[0];
8326 decal->texcoord2f[0][1] = t0[1];
8327 decal->texcoord2f[1][0] = t1[0];
8328 decal->texcoord2f[1][1] = t1[1];
8329 decal->texcoord2f[2][0] = t2[0];
8330 decal->texcoord2f[2][1] = t2[1];
8333 extern cvar_t cl_decals_bias;
8334 extern cvar_t cl_decals_models;
8335 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8336 static 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, int decalsequence)
8338 matrix4x4_t projection;
8339 decalsystem_t *decalsystem;
8342 const float *vertex3f;
8343 const msurface_t *surface;
8344 const msurface_t *surfaces;
8345 const int *surfacelist;
8346 const texture_t *texture;
8350 int surfacelistindex;
8353 int decalsurfaceindex;
8358 float localorigin[3];
8359 float localnormal[3];
8370 float points[2][9][3];
8374 decalsystem = &ent->decalsystem;
8376 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8378 R_DecalSystem_Reset(&ent->decalsystem);
8382 if (!model->brush.data_nodes && !cl_decals_models.integer)
8384 if (decalsystem->model)
8385 R_DecalSystem_Reset(decalsystem);
8389 if (decalsystem->model != model)
8390 R_DecalSystem_Reset(decalsystem);
8391 decalsystem->model = model;
8393 RSurf_ActiveModelEntity(ent, false, false);
8395 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8396 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8397 VectorNormalize(localnormal);
8398 localsize = worldsize*rsurface.inversematrixscale;
8399 ilocalsize = 1.0f / localsize;
8400 localmins[0] = localorigin[0] - localsize;
8401 localmins[1] = localorigin[1] - localsize;
8402 localmins[2] = localorigin[2] - localsize;
8403 localmaxs[0] = localorigin[0] + localsize;
8404 localmaxs[1] = localorigin[1] + localsize;
8405 localmaxs[2] = localorigin[2] + localsize;
8407 //VectorCopy(localnormal, planes[4]);
8408 //VectorVectors(planes[4], planes[2], planes[0]);
8409 AnglesFromVectors(angles, localnormal, NULL, false);
8410 AngleVectors(angles, planes[0], planes[2], planes[4]);
8411 VectorNegate(planes[0], planes[1]);
8412 VectorNegate(planes[2], planes[3]);
8413 VectorNegate(planes[4], planes[5]);
8414 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8415 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8416 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8417 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8418 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8419 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8424 matrix4x4_t forwardprojection;
8425 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8426 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8431 float projectionvector[4][3];
8432 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8433 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8434 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8435 projectionvector[0][0] = planes[0][0] * ilocalsize;
8436 projectionvector[0][1] = planes[1][0] * ilocalsize;
8437 projectionvector[0][2] = planes[2][0] * ilocalsize;
8438 projectionvector[1][0] = planes[0][1] * ilocalsize;
8439 projectionvector[1][1] = planes[1][1] * ilocalsize;
8440 projectionvector[1][2] = planes[2][1] * ilocalsize;
8441 projectionvector[2][0] = planes[0][2] * ilocalsize;
8442 projectionvector[2][1] = planes[1][2] * ilocalsize;
8443 projectionvector[2][2] = planes[2][2] * ilocalsize;
8444 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8445 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8446 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8447 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8451 dynamic = model->surfmesh.isanimated;
8452 vertex3f = rsurface.modelvertex3f;
8453 numsurfacelist = model->nummodelsurfaces;
8454 surfacelist = model->sortedmodelsurfaces;
8455 surfaces = model->data_surfaces;
8456 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8458 surfaceindex = surfacelist[surfacelistindex];
8459 surface = surfaces + surfaceindex;
8460 // skip transparent surfaces
8461 texture = surface->texture;
8462 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8464 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8466 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8468 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8469 numvertices = surface->num_vertices;
8470 numtriangles = surface->num_triangles;
8471 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8473 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8475 index = 3*e[cornerindex];
8476 VectorCopy(vertex3f + index, v[cornerindex]);
8479 //TriangleNormal(v[0], v[1], v[2], normal);
8480 //if (DotProduct(normal, localnormal) < 0.0f)
8482 // clip by each of the box planes formed from the projection matrix
8483 // if anything survives, we emit the decal
8484 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]);
8487 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]);
8490 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]);
8493 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]);
8496 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]);
8499 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]);
8502 // some part of the triangle survived, so we have to accept it...
8505 // dynamic always uses the original triangle
8507 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8509 index = 3*e[cornerindex];
8510 VectorCopy(vertex3f + index, v[cornerindex]);
8513 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8515 // convert vertex positions to texcoords
8516 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8517 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8518 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8519 // calculate distance fade from the projection origin
8520 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8521 f = bound(0.0f, f, 1.0f);
8522 c[cornerindex][0] = r * f;
8523 c[cornerindex][1] = g * f;
8524 c[cornerindex][2] = b * f;
8525 c[cornerindex][3] = 1.0f;
8526 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8529 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex+surface->num_firsttriangle, surfaceindex, decalsequence);
8531 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8532 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, surfaceindex, decalsequence);
8537 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8538 static void R_DecalSystem_ApplySplatEntities(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, int decalsequence)
8540 int renderentityindex;
8543 entity_render_t *ent;
8545 if (!cl_decals_newsystem.integer)
8548 worldmins[0] = worldorigin[0] - worldsize;
8549 worldmins[1] = worldorigin[1] - worldsize;
8550 worldmins[2] = worldorigin[2] - worldsize;
8551 worldmaxs[0] = worldorigin[0] + worldsize;
8552 worldmaxs[1] = worldorigin[1] + worldsize;
8553 worldmaxs[2] = worldorigin[2] + worldsize;
8555 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8557 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8559 ent = r_refdef.scene.entities[renderentityindex];
8560 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8563 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8567 typedef struct r_decalsystem_splatqueue_s
8576 r_decalsystem_splatqueue_t;
8578 int r_decalsystem_numqueued = 0;
8579 #define MAX_DECALSYSTEM_QUEUE 1024
8580 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8582 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)
8584 r_decalsystem_splatqueue_t *queue;
8586 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8589 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8590 VectorCopy(worldorigin, queue->worldorigin);
8591 VectorCopy(worldnormal, queue->worldnormal);
8592 Vector4Set(queue->color, r, g, b, a);
8593 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8594 queue->worldsize = worldsize;
8595 queue->decalsequence = cl.decalsequence++;
8598 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8601 r_decalsystem_splatqueue_t *queue;
8603 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8604 R_DecalSystem_ApplySplatEntities(queue->worldorigin, queue->worldnormal, queue->color[0], queue->color[1], queue->color[2], queue->color[3], queue->tcrange[0], queue->tcrange[1], queue->tcrange[2], queue->tcrange[3], queue->worldsize, queue->decalsequence);
8605 r_decalsystem_numqueued = 0;
8608 extern cvar_t cl_decals_max;
8609 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8612 decalsystem_t *decalsystem = &ent->decalsystem;
8619 if (!decalsystem->numdecals)
8622 if (r_showsurfaces.integer)
8625 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8627 R_DecalSystem_Reset(decalsystem);
8631 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
8632 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
8634 if (decalsystem->lastupdatetime)
8635 frametime = (cl.time - decalsystem->lastupdatetime);
8638 decalsystem->lastupdatetime = cl.time;
8639 decal = decalsystem->decals;
8640 numdecals = decalsystem->numdecals;
8642 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8644 if (decal->color4ub[0][3])
8646 decal->lived += frametime;
8647 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
8649 memset(decal, 0, sizeof(*decal));
8650 if (decalsystem->freedecal > i)
8651 decalsystem->freedecal = i;
8655 decal = decalsystem->decals;
8656 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
8659 // collapse the array by shuffling the tail decals into the gaps
8662 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
8663 decalsystem->freedecal++;
8664 if (decalsystem->freedecal == numdecals)
8666 decal[decalsystem->freedecal] = decal[--numdecals];
8669 decalsystem->numdecals = numdecals;
8673 // if there are no decals left, reset decalsystem
8674 R_DecalSystem_Reset(decalsystem);
8678 extern skinframe_t *decalskinframe;
8679 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8682 decalsystem_t *decalsystem = &ent->decalsystem;
8692 const unsigned char *surfacevisible = r_refdef.viewcache.world_surfacevisible;
8695 numdecals = decalsystem->numdecals;
8699 if (r_showsurfaces.integer)
8702 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8704 R_DecalSystem_Reset(decalsystem);
8708 // if the model is static it doesn't matter what value we give for
8709 // wantnormals and wanttangents, so this logic uses only rules applicable
8710 // to a model, knowing that they are meaningless otherwise
8711 if (ent == r_refdef.scene.worldentity)
8712 RSurf_ActiveWorldEntity();
8714 RSurf_ActiveModelEntity(ent, false, false);
8716 decalsystem->lastupdatetime = cl.time;
8717 decal = decalsystem->decals;
8719 fadedelay = cl_decals_time.value;
8720 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
8722 // update vertex positions for animated models
8723 v3f = decalsystem->vertex3f;
8724 c4f = decalsystem->color4f;
8725 t2f = decalsystem->texcoord2f;
8726 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8728 if (!decal->color4ub[0][3])
8731 if (decal->surfaceindex >= 0 && !surfacevisible[decal->surfaceindex])
8734 // update color values for fading decals
8735 if (decal->lived >= cl_decals_time.value)
8737 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
8738 alpha *= (1.0f/255.0f);
8741 alpha = 1.0f/255.0f;
8743 c4f[ 0] = decal->color4ub[0][0] * alpha;
8744 c4f[ 1] = decal->color4ub[0][1] * alpha;
8745 c4f[ 2] = decal->color4ub[0][2] * alpha;
8747 c4f[ 4] = decal->color4ub[1][0] * alpha;
8748 c4f[ 5] = decal->color4ub[1][1] * alpha;
8749 c4f[ 6] = decal->color4ub[1][2] * alpha;
8751 c4f[ 8] = decal->color4ub[2][0] * alpha;
8752 c4f[ 9] = decal->color4ub[2][1] * alpha;
8753 c4f[10] = decal->color4ub[2][2] * alpha;
8756 t2f[0] = decal->texcoord2f[0][0];
8757 t2f[1] = decal->texcoord2f[0][1];
8758 t2f[2] = decal->texcoord2f[1][0];
8759 t2f[3] = decal->texcoord2f[1][1];
8760 t2f[4] = decal->texcoord2f[2][0];
8761 t2f[5] = decal->texcoord2f[2][1];
8763 // update vertex positions for animated models
8764 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8766 e = rsurface.modelelement3i + 3*decal->triangleindex;
8767 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8768 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8769 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8773 VectorCopy(decal->vertex3f[0], v3f);
8774 VectorCopy(decal->vertex3f[1], v3f + 3);
8775 VectorCopy(decal->vertex3f[2], v3f + 6);
8786 r_refdef.stats.drawndecals += numtris;
8787 // now render the decals all at once
8788 // (this assumes they all use one particle font texture!)
8789 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, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
8790 R_Mesh_ResetTextureState();
8791 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8792 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8793 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8794 R_SetupGenericShader(true);
8795 GL_DepthMask(false);
8796 GL_DepthRange(0, 1);
8797 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
8799 GL_CullFace(GL_NONE);
8800 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8801 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8802 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8803 GL_LockArrays(0, numtris * 3);
8804 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
8805 GL_LockArrays(0, 0);
8809 static void R_DrawModelDecals(void)
8813 // fade faster when there are too many decals
8814 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
8815 for (i = 0;i < r_refdef.scene.numentities;i++)
8816 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
8818 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
8819 for (i = 0;i < r_refdef.scene.numentities;i++)
8820 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
8821 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
8823 R_DecalSystem_ApplySplatEntitiesQueue();
8825 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
8826 for (i = 0;i < r_refdef.scene.numentities;i++)
8827 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
8829 r_refdef.stats.totaldecals += numdecals;
8831 if (r_showsurfaces.integer)
8834 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
8836 if (!r_drawentities.integer)
8839 for (i = 0;i < r_refdef.scene.numentities;i++)
8841 if (!r_refdef.viewcache.entityvisible[i])
8843 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
8844 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
8848 void R_DrawDebugModel(void)
8850 entity_render_t *ent = rsurface.entity;
8851 int i, j, k, l, flagsmask;
8852 const int *elements;
8854 const msurface_t *surface;
8855 dp_model_t *model = ent->model;
8858 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8860 R_Mesh_ColorPointer(NULL, 0, 0);
8861 R_Mesh_ResetTextureState();
8862 R_SetupGenericShader(false);
8863 GL_DepthRange(0, 1);
8864 GL_DepthTest(!r_showdisabledepthtest.integer);
8865 GL_DepthMask(false);
8866 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8868 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8870 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8871 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8873 if (brush->colbrushf && brush->colbrushf->numtriangles)
8875 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8876 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);
8877 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8880 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8882 if (surface->num_collisiontriangles)
8884 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8885 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);
8886 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8891 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8893 if (r_showtris.integer || r_shownormals.integer)
8895 if (r_showdisabledepthtest.integer)
8897 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8898 GL_DepthMask(false);
8902 GL_BlendFunc(GL_ONE, GL_ZERO);
8905 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8907 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8909 rsurface.texture = R_GetCurrentTexture(surface->texture);
8910 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8912 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8913 if (r_showtris.value > 0)
8915 if (!rsurface.texture->currentlayers->depthmask)
8916 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8917 else if (ent == r_refdef.scene.worldentity)
8918 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8920 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8921 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8922 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8923 R_Mesh_ColorPointer(NULL, 0, 0);
8924 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8925 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8926 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8927 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);
8928 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8931 if (r_shownormals.value < 0)
8934 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8936 VectorCopy(rsurface.vertex3f + l * 3, v);
8937 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8938 qglVertex3f(v[0], v[1], v[2]);
8939 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8940 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8941 qglVertex3f(v[0], v[1], v[2]);
8946 if (r_shownormals.value > 0)
8949 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8951 VectorCopy(rsurface.vertex3f + l * 3, v);
8952 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8953 qglVertex3f(v[0], v[1], v[2]);
8954 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8955 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8956 qglVertex3f(v[0], v[1], v[2]);
8961 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8963 VectorCopy(rsurface.vertex3f + l * 3, v);
8964 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8965 qglVertex3f(v[0], v[1], v[2]);
8966 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8967 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8968 qglVertex3f(v[0], v[1], v[2]);
8973 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8975 VectorCopy(rsurface.vertex3f + l * 3, v);
8976 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8977 qglVertex3f(v[0], v[1], v[2]);
8978 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8979 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8980 qglVertex3f(v[0], v[1], v[2]);
8987 rsurface.texture = NULL;
8991 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8992 int r_maxsurfacelist = 0;
8993 const msurface_t **r_surfacelist = NULL;
8994 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8996 int i, j, endj, f, flagsmask;
8998 dp_model_t *model = r_refdef.scene.worldmodel;
8999 msurface_t *surfaces;
9000 unsigned char *update;
9001 int numsurfacelist = 0;
9005 if (r_maxsurfacelist < model->num_surfaces)
9007 r_maxsurfacelist = model->num_surfaces;
9009 Mem_Free((msurface_t**)r_surfacelist);
9010 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9013 RSurf_ActiveWorldEntity();
9015 surfaces = model->data_surfaces;
9016 update = model->brushq1.lightmapupdateflags;
9018 // update light styles on this submodel
9019 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9021 model_brush_lightstyleinfo_t *style;
9022 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9024 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9026 int *list = style->surfacelist;
9027 style->value = r_refdef.scene.lightstylevalue[style->style];
9028 for (j = 0;j < style->numsurfaces;j++)
9029 update[list[j]] = true;
9034 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9039 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9045 rsurface.uselightmaptexture = false;
9046 rsurface.texture = NULL;
9047 rsurface.rtlight = NULL;
9049 // add visible surfaces to draw list
9050 for (i = 0;i < model->nummodelsurfaces;i++)
9052 j = model->sortedmodelsurfaces[i];
9053 if (r_refdef.viewcache.world_surfacevisible[j])
9054 r_surfacelist[numsurfacelist++] = surfaces + j;
9056 // update lightmaps if needed
9058 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9059 if (r_refdef.viewcache.world_surfacevisible[j])
9061 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9062 // don't do anything if there were no surfaces
9063 if (!numsurfacelist)
9065 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9068 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
9069 GL_AlphaTest(false);
9071 // add to stats if desired
9072 if (r_speeds.integer && !skysurfaces && !depthonly)
9074 r_refdef.stats.world_surfaces += numsurfacelist;
9075 for (j = 0;j < numsurfacelist;j++)
9076 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9079 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9082 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
9084 int i, j, endj, f, flagsmask;
9086 dp_model_t *model = ent->model;
9087 msurface_t *surfaces;
9088 unsigned char *update;
9089 int numsurfacelist = 0;
9093 if (r_maxsurfacelist < model->num_surfaces)
9095 r_maxsurfacelist = model->num_surfaces;
9097 Mem_Free((msurface_t **)r_surfacelist);
9098 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9101 // if the model is static it doesn't matter what value we give for
9102 // wantnormals and wanttangents, so this logic uses only rules applicable
9103 // to a model, knowing that they are meaningless otherwise
9104 if (ent == r_refdef.scene.worldentity)
9105 RSurf_ActiveWorldEntity();
9106 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9107 RSurf_ActiveModelEntity(ent, false, false);
9109 RSurf_ActiveModelEntity(ent, false, false);
9111 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && vid.support.arb_fragment_shader);
9113 surfaces = model->data_surfaces;
9114 update = model->brushq1.lightmapupdateflags;
9116 // update light styles
9117 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9119 model_brush_lightstyleinfo_t *style;
9120 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9122 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9124 int *list = style->surfacelist;
9125 style->value = r_refdef.scene.lightstylevalue[style->style];
9126 for (j = 0;j < style->numsurfaces;j++)
9127 update[list[j]] = true;
9132 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9137 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9143 rsurface.uselightmaptexture = false;
9144 rsurface.texture = NULL;
9145 rsurface.rtlight = NULL;
9147 // add visible surfaces to draw list
9148 for (i = 0;i < model->nummodelsurfaces;i++)
9149 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9150 // don't do anything if there were no surfaces
9151 if (!numsurfacelist)
9153 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9156 // update lightmaps if needed
9158 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9160 R_BuildLightMap(ent, surfaces + j);
9161 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
9162 GL_AlphaTest(false);
9164 // add to stats if desired
9165 if (r_speeds.integer && !skysurfaces && !depthonly)
9167 r_refdef.stats.entities_surfaces += numsurfacelist;
9168 for (j = 0;j < numsurfacelist;j++)
9169 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9172 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9175 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
9177 static texture_t texture;
9178 static msurface_t surface;
9179 const msurface_t *surfacelist = &surface;
9181 // fake enough texture and surface state to render this geometry
9183 texture.update_lastrenderframe = -1; // regenerate this texture
9184 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9185 texture.currentskinframe = skinframe;
9186 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9187 texture.specularscalemod = 1;
9188 texture.specularpowermod = 1;
9190 surface.texture = &texture;
9191 surface.num_triangles = numtriangles;
9192 surface.num_firsttriangle = firsttriangle;
9193 surface.num_vertices = numvertices;
9194 surface.num_firstvertex = firstvertex;
9197 rsurface.texture = R_GetCurrentTexture(surface.texture);
9198 rsurface.uselightmaptexture = false;
9199 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);