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_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"};
58 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
59 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
60 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
61 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
62 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
63 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)"};
64 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
65 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
66 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"};
67 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"};
68 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
69 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"};
70 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"};
71 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"};
72 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
73 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
74 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
75 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
76 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)"};
77 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)"};
78 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
79 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
80 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
81 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
82 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
83 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
84 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
85 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."};
86 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
87 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
88 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
89 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."};
90 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
91 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
92 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"};
93 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"};
94 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
95 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
96 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
97 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
99 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
100 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
101 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
102 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
103 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
104 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
105 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
106 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
108 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
109 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
110 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
112 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)"};
113 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
114 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
115 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
116 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
117 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)"};
118 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)"};
119 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)"};
120 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_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
123 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
124 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"};
125 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
126 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
128 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
129 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
130 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
131 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
133 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
134 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
135 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
136 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
137 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
138 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
139 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
141 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
142 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
143 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
144 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)"};
146 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"};
148 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"};
150 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
152 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
153 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
154 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"};
155 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
156 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
157 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
158 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
160 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
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 MODE_DEPTH_OR_SHADOW\n"
462 "#ifdef VERTEX_SHADER\n"
465 " gl_Position = ftransform();\n"
468 "#else // !MODE_DEPTH_ORSHADOW\n"
469 "#ifdef MODE_SHOWDEPTH\n"
470 "#ifdef VERTEX_SHADER\n"
473 " gl_Position = ftransform();\n"
474 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
478 "#ifdef FRAGMENT_SHADER\n"
481 " gl_FragColor = gl_Color;\n"
484 "#else // !MODE_SHOWDEPTH\n"
485 "#ifdef MODE_POSTPROCESS\n"
486 "#ifdef VERTEX_SHADER\n"
489 " gl_Position = ftransform();\n"
490 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
492 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
497 "#ifdef FRAGMENT_SHADER\n"
498 "uniform sampler2D Texture_First;\n"
500 "uniform sampler2D Texture_Second;\n"
502 "#ifdef USEGAMMARAMPS\n"
503 "uniform sampler2D Texture_GammaRamps;\n"
505 "#ifdef USESATURATION\n"
506 "uniform float Saturation;\n"
508 "#ifdef USEVIEWTINT\n"
509 "uniform vec4 TintColor;\n"
511 "//uncomment these if you want to use them:\n"
512 "uniform vec4 UserVec1;\n"
513 "// uniform vec4 UserVec2;\n"
514 "// uniform vec4 UserVec3;\n"
515 "// uniform vec4 UserVec4;\n"
516 "// uniform float ClientTime;\n"
517 "uniform vec2 PixelSize;\n"
520 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
522 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
524 "#ifdef USEVIEWTINT\n"
525 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
528 "#ifdef USEPOSTPROCESSING\n"
529 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
530 "// 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"
531 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
532 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
533 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
534 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
535 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
536 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
539 "#ifdef USESATURATION\n"
540 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
541 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
542 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
543 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
546 "#ifdef USEGAMMARAMPS\n"
547 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
548 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
549 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
553 "#else // !MODE_POSTPROCESS\n"
554 "#ifdef MODE_GENERIC\n"
555 "#ifdef VERTEX_SHADER\n"
558 " gl_FrontColor = gl_Color;\n"
559 "#ifdef USEDIFFUSE\n"
560 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
562 "#ifdef USESPECULAR\n"
563 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
565 " gl_Position = ftransform();\n"
569 "#ifdef FRAGMENT_SHADER\n"
570 "#ifdef USEDIFFUSE\n"
571 "uniform sampler2D Texture_First;\n"
573 "#ifdef USESPECULAR\n"
574 "uniform sampler2D Texture_Second;\n"
579 " gl_FragColor = gl_Color;\n"
580 "#ifdef USEDIFFUSE\n"
581 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
584 "#ifdef USESPECULAR\n"
585 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
587 "#ifdef USECOLORMAPPING\n"
588 " gl_FragColor *= tex2;\n"
591 " gl_FragColor += tex2;\n"
593 "#ifdef USEVERTEXTEXTUREBLEND\n"
594 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
598 "#else // !MODE_GENERIC\n"
599 "#ifdef MODE_BLOOMBLUR\n"
600 "#ifdef VERTEX_SHADER\n"
603 " gl_FrontColor = gl_Color;\n"
604 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
605 " gl_Position = ftransform();\n"
609 "#ifdef FRAGMENT_SHADER\n"
610 "uniform sampler2D Texture_First;\n"
611 "uniform vec4 BloomBlur_Parameters;\n"
616 " vec2 tc = gl_TexCoord[0].xy;\n"
617 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
618 " tc += BloomBlur_Parameters.xy;\n"
619 " for (i = 1;i < SAMPLES;i++)\n"
621 " color += texture2D(Texture_First, tc).rgb;\n"
622 " tc += BloomBlur_Parameters.xy;\n"
624 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
627 "#else // !MODE_BLOOMBLUR\n"
628 "#ifdef MODE_REFRACTION\n"
629 "varying vec2 TexCoord;\n"
630 "varying vec4 ModelViewProjectionPosition;\n"
631 "#ifdef VERTEX_SHADER\n"
635 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
636 " gl_Position = ftransform();\n"
637 " ModelViewProjectionPosition = gl_Position;\n"
641 "#ifdef FRAGMENT_SHADER\n"
642 "uniform sampler2D Texture_Normal;\n"
643 "uniform sampler2D Texture_Refraction;\n"
644 "uniform sampler2D Texture_Reflection;\n"
646 "uniform vec4 DistortScaleRefractReflect;\n"
647 "uniform vec4 ScreenScaleRefractReflect;\n"
648 "uniform vec4 ScreenCenterRefractReflect;\n"
649 "uniform vec4 RefractColor;\n"
650 "uniform vec4 ReflectColor;\n"
651 "uniform float ReflectFactor;\n"
652 "uniform float ReflectOffset;\n"
656 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
657 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
658 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
659 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
660 " // FIXME temporary hack to detect the case that the reflection\n"
661 " // gets blackened at edges due to leaving the area that contains actual\n"
663 " // Remove this 'ack once we have a better way to stop this thing from\n"
665 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
666 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
667 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
668 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
669 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
670 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
673 "#else // !MODE_REFRACTION\n"
674 "#ifdef MODE_WATER\n"
675 "varying vec2 TexCoord;\n"
676 "varying vec3 EyeVector;\n"
677 "varying vec4 ModelViewProjectionPosition;\n"
678 "#ifdef VERTEX_SHADER\n"
679 "uniform vec3 EyePosition;\n"
683 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
684 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
685 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
686 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
687 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
688 " gl_Position = ftransform();\n"
689 " ModelViewProjectionPosition = gl_Position;\n"
693 "#ifdef FRAGMENT_SHADER\n"
694 "uniform sampler2D Texture_Normal;\n"
695 "uniform sampler2D Texture_Refraction;\n"
696 "uniform sampler2D Texture_Reflection;\n"
698 "uniform vec4 DistortScaleRefractReflect;\n"
699 "uniform vec4 ScreenScaleRefractReflect;\n"
700 "uniform vec4 ScreenCenterRefractReflect;\n"
701 "uniform vec4 RefractColor;\n"
702 "uniform vec4 ReflectColor;\n"
703 "uniform float ReflectFactor;\n"
704 "uniform float ReflectOffset;\n"
708 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
709 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
710 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
711 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
712 " // FIXME temporary hack to detect the case that the reflection\n"
713 " // gets blackened at edges due to leaving the area that contains actual\n"
715 " // Remove this 'ack once we have a better way to stop this thing from\n"
717 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
718 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
719 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
720 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
721 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
722 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
723 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
724 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
725 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
726 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
727 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
728 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
731 "#else // !MODE_WATER\n"
733 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
734 "# extension GL_ARB_texture_rectangle : enable\n"
737 "#ifdef USESHADOWMAP2D\n"
738 "# ifdef GL_EXT_gpu_shader4\n"
739 "# extension GL_EXT_gpu_shader4 : enable\n"
741 "# ifdef GL_ARB_texture_gather\n"
742 "# extension GL_ARB_texture_gather : enable\n"
744 "# ifdef GL_AMD_texture_texture4\n"
745 "# extension GL_AMD_texture_texture4 : enable\n"
750 "#ifdef USESHADOWMAPCUBE\n"
751 "# extension GL_EXT_gpu_shader4 : enable\n"
754 "#ifdef USESHADOWSAMPLER\n"
755 "# extension GL_ARB_shadow : enable\n"
758 "// common definitions between vertex shader and fragment shader:\n"
760 "//#ifdef __GLSL_CG_DATA_TYPES\n"
761 "//# define myhalf half\n"
762 "//# define myhalf2 half2\n"
763 "//# define myhalf3half3\n"
764 "//# define myhalf4 half4\n"
766 "# define myhalf float\n"
767 "# define myhalf2 vec2\n"
768 "# define myhalf3 vec3\n"
769 "# define myhalf4 vec4\n"
772 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
776 "varying vec2 TexCoord;\n"
777 "#ifdef USEVERTEXTEXTUREBLEND\n"
778 "varying vec2 TexCoord2;\n"
780 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
781 "#define USELIGHTMAP\n"
782 "varying vec2 TexCoordLightmap;\n"
785 "#ifdef MODE_LIGHTSOURCE\n"
786 "varying vec3 CubeVector;\n"
789 "#ifdef MODE_LIGHTSOURCE\n"
790 "varying vec3 LightVector;\n"
792 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
793 "varying vec3 LightVector;\n"
796 "#if defined(USEOFFSETMAPPING) || defined(USEFOG) || defined(USESPECULAR)\n"
797 "#define USEEYEVECTOR\n"
798 "varying vec3 EyeVector;\n"
801 "varying vec3 EyeVectorModelSpace;\n"
802 "varying float FogPlaneVertexDist;\n"
805 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
806 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
807 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
809 "#ifdef USEREFLECTION\n"
810 "varying vec4 ModelViewProjectionPosition;\n"
812 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
813 "varying vec4 ModelViewPosition;\n"
816 "uniform vec3 LightPosition;\n"
817 "uniform vec3 EyePosition;\n"
818 "uniform vec3 LightDir;\n"
819 "uniform vec4 FogPlane;\n"
825 "// vertex shader specific:\n"
826 "#ifdef VERTEX_SHADER\n"
828 "// 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"
830 "#ifdef MODE_DEFERREDGEOMETRY\n"
833 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
834 "#ifdef USEVERTEXTEXTUREBLEND\n"
835 " gl_FrontColor = gl_Color;\n"
836 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
839 " // transform unnormalized eye direction into tangent space\n"
841 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
842 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
844 "#ifdef USEOFFSETMAPPING\n"
846 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
848 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
849 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
850 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
853 " VectorS = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz).xyz;\n"
854 " VectorT = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz).xyz;\n"
855 " VectorR = normalize(gl_NormalMatrix * gl_MultiTexCoord3.xyz).xyz;\n"
856 " gl_Position = ftransform();\n"
858 "#else // !MODE_DEFERREDGEOMETRY\n"
859 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
862 " ModelViewPosition = gl_ModelViewMatrix * gl_Vertex;\n"
863 " gl_Position = ftransform();\n"
865 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
868 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
869 " gl_FrontColor = gl_Color;\n"
871 " // copy the surface texcoord\n"
872 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
873 "#ifdef USEVERTEXTEXTUREBLEND\n"
874 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
876 "#ifdef USELIGHTMAP\n"
877 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
880 "#ifdef MODE_LIGHTSOURCE\n"
881 " // transform vertex position into light attenuation/cubemap space\n"
882 " // (-1 to +1 across the light box)\n"
883 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
885 "# ifdef USEDIFFUSE\n"
886 " // transform unnormalized light direction into tangent space\n"
887 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
888 " // normalize it per pixel)\n"
889 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
890 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
891 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
892 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
896 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
897 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
898 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
899 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
902 " // transform unnormalized eye direction into tangent space\n"
903 "#ifdef USEEYEVECTOR\n"
905 " vec3 EyeVectorModelSpace;\n"
907 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
908 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
909 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
910 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
914 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
917 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
918 " VectorS = gl_MultiTexCoord1.xyz;\n"
919 " VectorT = gl_MultiTexCoord2.xyz;\n"
920 " VectorR = gl_MultiTexCoord3.xyz;\n"
923 "//#if defined(USEREFLECTION)\n"
924 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
925 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
926 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
929 "// transform vertex to camera space, using ftransform to match non-VS\n"
931 " gl_Position = ftransform();\n"
933 "#ifdef USEREFLECTION\n"
934 " ModelViewProjectionPosition = gl_Position;\n"
937 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
938 "#endif // !MODE_DEFERREDGEOMETRY\n"
940 "#endif // VERTEX_SHADER\n"
945 "// fragment shader specific:\n"
946 "#ifdef FRAGMENT_SHADER\n"
948 "uniform sampler2D Texture_Normal;\n"
949 "uniform sampler2D Texture_Color;\n"
950 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
951 "uniform sampler2D Texture_Gloss;\n"
954 "uniform sampler2D Texture_Glow;\n"
956 "#ifdef USEVERTEXTEXTUREBLEND\n"
957 "uniform sampler2D Texture_SecondaryNormal;\n"
958 "uniform sampler2D Texture_SecondaryColor;\n"
959 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
960 "uniform sampler2D Texture_SecondaryGloss;\n"
963 "uniform sampler2D Texture_SecondaryGlow;\n"
966 "#ifdef USECOLORMAPPING\n"
967 "uniform sampler2D Texture_Pants;\n"
968 "uniform sampler2D Texture_Shirt;\n"
971 "uniform sampler2D Texture_FogMask;\n"
973 "#ifdef USELIGHTMAP\n"
974 "uniform sampler2D Texture_Lightmap;\n"
976 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
977 "uniform sampler2D Texture_Deluxemap;\n"
979 "#ifdef USEREFLECTION\n"
980 "uniform sampler2D Texture_Reflection;\n"
983 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
984 "uniform sampler2DRect Texture_ScreenDepth;\n"
985 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
987 "#ifdef USEDEFERREDLIGHTMAP\n"
988 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
989 "uniform sampler2DRect Texture_ScreenSpecular;\n"
992 "uniform myhalf3 LightColor;\n"
993 "uniform myhalf3 AmbientColor;\n"
994 "uniform myhalf3 DiffuseColor;\n"
995 "uniform myhalf3 SpecularColor;\n"
996 "uniform myhalf3 Color_Pants;\n"
997 "uniform myhalf3 Color_Shirt;\n"
998 "uniform myhalf3 FogColor;\n"
1000 "uniform myhalf4 TintColor;\n"
1003 "#ifdef USEREFLECTION\n"
1004 "uniform vec4 DistortScaleRefractReflect;\n"
1005 "uniform vec4 ScreenScaleRefractReflect;\n"
1006 "uniform vec4 ScreenCenterRefractReflect;\n"
1007 "uniform myhalf4 ReflectColor;\n"
1011 "uniform myhalf3 GlowColor;\n"
1013 "uniform myhalf SceneBrightness;\n"
1015 "uniform myhalf AmbientScale;\n"
1016 "uniform myhalf DiffuseScale;\n"
1017 "#ifdef USESPECULAR\n"
1018 "uniform myhalf SpecularScale;\n"
1019 "uniform myhalf SpecularPower;\n"
1025 "uniform float FogRangeRecip;\n"
1026 "uniform float FogPlaneViewDist;\n"
1027 "uniform float FogHeightFade;\n"
1028 "myhalf FogVertex(void)\n"
1031 "#ifdef USEFOGOUTSIDE\n"
1032 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1034 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1036 " return myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1040 "#ifdef USEOFFSETMAPPING\n"
1041 "uniform float OffsetMapping_Scale;\n"
1042 "uniform float OffsetMapping_Bias;\n"
1043 "vec2 OffsetMapping(vec2 TexCoord)\n"
1045 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1046 " // 14 sample relief mapping: linear search and then binary search\n"
1047 " // this basically steps forward a small amount repeatedly until it finds\n"
1048 " // itself inside solid, then jitters forward and back using decreasing\n"
1049 " // amounts to find the impact\n"
1050 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1051 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1052 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1053 " vec3 RT = vec3(TexCoord, 1);\n"
1054 " OffsetVector *= 0.1;\n"
1055 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1056 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1057 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1058 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1059 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1060 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1061 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1062 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1063 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1064 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1065 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1066 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1067 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1068 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1071 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1072 " // this basically moves forward the full distance, and then backs up based\n"
1073 " // on height of samples\n"
1074 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1075 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1076 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1077 " TexCoord += OffsetVector;\n"
1078 " OffsetVector *= 0.333;\n"
1079 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1080 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1081 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1082 " return TexCoord;\n"
1085 "#endif // USEOFFSETMAPPING\n"
1087 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1088 "uniform sampler2D Texture_Attenuation;\n"
1089 "uniform samplerCube Texture_Cube;\n"
1091 "#define showshadowmap 0\n"
1093 "#ifdef USESHADOWMAPRECT\n"
1094 "# ifdef USESHADOWSAMPLER\n"
1095 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1097 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1101 "#ifdef USESHADOWMAP2D\n"
1102 "# ifdef USESHADOWSAMPLER\n"
1103 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1105 "uniform sampler2D Texture_ShadowMap2D;\n"
1109 "#ifdef USESHADOWMAPVSDCT\n"
1110 "uniform samplerCube Texture_CubeProjection;\n"
1113 "#ifdef USESHADOWMAPCUBE\n"
1114 "# ifdef USESHADOWSAMPLER\n"
1115 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1117 "uniform samplerCube Texture_ShadowMapCube;\n"
1121 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1122 "uniform vec2 ShadowMap_TextureScale;\n"
1123 "uniform vec4 ShadowMap_Parameters;\n"
1126 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1127 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1129 " vec3 adir = abs(dir);\n"
1130 "# ifndef USESHADOWMAPVSDCT\n"
1134 " if (adir.x > adir.y)\n"
1136 " if (adir.x > adir.z) // X\n"
1140 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1146 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1151 " if (adir.y > adir.z) // Y\n"
1155 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1161 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1165 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1166 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1167 " stc.z += ShadowMap_Parameters.z;\n"
1168 "# if showshadowmap\n"
1169 " stc.xy *= ShadowMap_TextureScale;\n"
1173 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1174 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1175 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1176 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1177 " stc.z += ShadowMap_Parameters.z;\n"
1178 "# if showshadowmap\n"
1179 " stc.xy *= ShadowMap_TextureScale;\n"
1184 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1186 "#ifdef USESHADOWMAPCUBE\n"
1187 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1189 " vec3 adir = abs(dir);\n"
1190 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1194 "#if !showshadowmap\n"
1195 "# ifdef USESHADOWMAPRECT\n"
1196 "float ShadowMapCompare(vec3 dir)\n"
1198 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1200 "# ifdef USESHADOWSAMPLER\n"
1202 "# ifdef USESHADOWMAPPCF\n"
1203 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1204 " 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"
1206 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1211 "# ifdef USESHADOWMAPPCF\n"
1212 "# if USESHADOWMAPPCF > 1\n"
1213 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1214 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1215 " 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"
1216 " 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"
1217 " 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"
1218 " 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"
1219 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1220 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1222 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1223 " vec2 offset = fract(shadowmaptc.xy);\n"
1224 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1225 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1226 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1227 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1228 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1231 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1239 "# ifdef USESHADOWMAP2D\n"
1240 "float ShadowMapCompare(vec3 dir)\n"
1242 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1245 "# ifdef USESHADOWSAMPLER\n"
1246 "# ifdef USESHADOWMAPPCF\n"
1247 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1248 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1249 " 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"
1251 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1254 "# ifdef USESHADOWMAPPCF\n"
1255 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1256 "# ifdef GL_ARB_texture_gather\n"
1257 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1259 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1261 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1262 " center *= ShadowMap_TextureScale;\n"
1263 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1264 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1265 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1266 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1267 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1268 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1269 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1271 "# ifdef GL_EXT_gpu_shader4\n"
1272 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1274 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1276 "# if USESHADOWMAPPCF > 1\n"
1277 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1278 " center *= ShadowMap_TextureScale;\n"
1279 " 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"
1280 " 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"
1281 " 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"
1282 " 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"
1283 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1284 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1286 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1287 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1288 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1289 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1290 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1291 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1295 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1302 "# ifdef USESHADOWMAPCUBE\n"
1303 "float ShadowMapCompare(vec3 dir)\n"
1305 " // apply depth texture cubemap as light filter\n"
1306 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1308 "# ifdef USESHADOWSAMPLER\n"
1309 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1311 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1317 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1319 "#ifdef MODE_DEFERREDGEOMETRY\n"
1322 "#ifdef USEOFFSETMAPPING\n"
1323 " // apply offsetmapping\n"
1324 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1325 "#define TexCoord TexCoordOffset\n"
1328 " // get diffuse alpha in case we're using alpha masking\n"
1329 " float alpha = float(texture2D(Texture_Color, TexCoord).a);\n"
1330 "#ifdef USEVERTEXTEXTUREBLEND\n"
1331 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1332 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1333 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1337 "#ifdef USEVERTEXTEXTUREBLEND\n"
1338 " vec3 surfacenormal = normalize(mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5));\n"
1340 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5));\n"
1343 " // fade the normal in fog so that lights don't have to consider fog\n"
1345 " surfacenormal *= FogVertex();\n"
1348 " gl_FragColor = vec4((surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5,0.5,0.5), alpha);\n"
1350 "#else // !MODE_DEFERREDGEOMETRY\n"
1351 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1352 "uniform mat4 ViewToLight;\n"
1353 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1354 "uniform vec2 ScreenToDepth;\n"
1355 "uniform float DeferredDiffuseRange;\n"
1356 "uniform float DeferredSpecularRange;\n"
1359 " // calculate viewspace pixel position\n"
1361 " position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1362 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1363 " // decode viewspace pixel normal\n"
1364 " myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1365 " myhalf fade = 1;\n"
1366 " myhalf3 surfacenormal = normalmap.rgb * 2 - myhalf3(1,1,1);\n"
1368 " // extract fogged brightness from length of surfacenormal (because it was written this way)\n"
1369 " fade *= length(surfacenormal);\n"
1370 " surfacenormal = normalize(surfacenormal);\n"
1372 " // surfacenormal = pixel normal in viewspace\n"
1373 " // LightVector = pixel to light in viewspace\n"
1374 " // CubeVector = position in lightspace\n"
1375 " // eyevector = pixel to view in viewspace\n"
1376 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1377 " fade *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1378 "#ifdef USEDIFFUSE\n"
1379 " // get the light normal\n"
1380 " myhalf3 diffusenormal = myhalf3(normalize(LightPosition - position));\n"
1381 " // calculate diffuse shading\n"
1382 " myhalf diffuse = AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1383 "# ifdef USESPECULAR\n"
1384 " // calculate directional shading\n"
1385 " vec3 eyevector = position * -1.0;\n"
1386 "# ifdef USEEXACTSPECULARMATH\n"
1387 " myhalf specular = SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1389 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(eyevector)));\n"
1390 " myhalf specular = SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1393 " myhalf specular = 0;\n"
1396 " myhalf diffuse = 1;\n"
1397 " myhalf specular = 0;\n"
1400 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1401 " fade *= ShadowMapCompare(CubeVector);\n"
1404 " diffuse *= DeferredDiffuseRange;\n"
1405 " specular *= DeferredSpecularRange;\n"
1407 " myhalf3 lightcolor = TintColor.rgb * fade;\n"
1408 "# ifdef USECUBEFILTER\n"
1409 " lightcolor *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1412 " gl_FragData[0] = vec4(lightcolor * diffuse, 1.0);\n"
1413 " gl_FragData[1] = vec4(lightcolor * specular, 1.0);\n"
1415 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1416 "#ifdef USEDEFERREDLIGHTMAP\n"
1417 "uniform float DeferredDiffuseRange;\n"
1418 "uniform float DeferredSpecularRange;\n"
1422 "#ifdef USEOFFSETMAPPING\n"
1423 " // apply offsetmapping\n"
1424 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1425 "#define TexCoord TexCoordOffset\n"
1428 " // combine the diffuse textures (base, pants, shirt)\n"
1429 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1430 "#ifdef USECOLORMAPPING\n"
1431 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1433 "#ifdef USEVERTEXTEXTUREBLEND\n"
1434 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1435 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1436 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1437 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1439 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1442 " // get the surface normal\n"
1443 "#ifdef USEDIFFUSE\n"
1444 "# ifdef USEVERTEXTEXTUREBLEND\n"
1445 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1447 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1451 " // get the gloss color\n"
1452 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1453 "# ifdef USEVERTEXTEXTUREBLEND\n"
1454 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1456 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1460 "#ifdef USEDEFERREDLIGHTMAP\n"
1461 " myhalf3 deferredcolor = color.rgb * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredDiffuseRange + glosscolor.rgb * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredSpecularRange;\n"
1466 "#ifdef MODE_LIGHTSOURCE\n"
1467 " // light source\n"
1469 " // calculate surface normal, light normal, and specular normal\n"
1470 " // compute color intensity for the two textures (colormap and glossmap)\n"
1471 " // scale by light color and attenuation as efficiently as possible\n"
1472 " // (do as much scalar math as possible rather than vector math)\n"
1473 "# ifdef USEDIFFUSE\n"
1474 " // get the light normal\n"
1475 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1477 "# ifdef USESPECULAR\n"
1478 "# ifndef USEEXACTSPECULARMATH\n"
1479 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1482 " // calculate directional shading\n"
1483 "# ifdef USEEXACTSPECULARMATH\n"
1484 " 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"
1486 " 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"
1489 "# ifdef USEDIFFUSE\n"
1490 " // calculate directional shading\n"
1491 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1493 " // calculate directionless shading\n"
1494 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1498 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1499 "#if !showshadowmap\n"
1500 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1504 "# ifdef USECUBEFILTER\n"
1505 " // apply light cubemap filter\n"
1506 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1507 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1509 "#endif // MODE_LIGHTSOURCE\n"
1514 "#ifdef MODE_LIGHTDIRECTION\n"
1515 " // directional model lighting\n"
1516 "# ifdef USEDIFFUSE\n"
1517 " // get the light normal\n"
1518 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1520 "# ifdef USESPECULAR\n"
1521 " // calculate directional shading\n"
1522 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1523 "# ifdef USEEXACTSPECULARMATH\n"
1524 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1526 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1527 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1530 "# ifdef USEDIFFUSE\n"
1532 " // calculate directional shading\n"
1533 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1535 " color.rgb *= AmbientColor;\n"
1538 "#endif // MODE_LIGHTDIRECTION\n"
1543 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1544 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1546 " // get the light normal\n"
1547 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1548 " myhalf3 diffusenormal;\n"
1549 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1550 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1551 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1552 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1553 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1554 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1555 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1556 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1557 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1558 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1559 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1560 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1561 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1562 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1563 "# ifdef USESPECULAR\n"
1564 "# ifdef USEEXACTSPECULARMATH\n"
1565 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1567 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1568 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1572 " // apply lightmap color\n"
1573 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1574 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1579 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1580 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1582 " // get the light normal\n"
1583 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1584 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1585 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1586 "# ifdef USESPECULAR\n"
1587 "# ifdef USEEXACTSPECULARMATH\n"
1588 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1590 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1591 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1595 " // apply lightmap color\n"
1596 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1597 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1602 "#ifdef MODE_LIGHTMAP\n"
1603 " // apply lightmap color\n"
1604 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1605 "#endif // MODE_LIGHTMAP\n"
1610 "#ifdef MODE_VERTEXCOLOR\n"
1611 " // apply lightmap color\n"
1612 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1613 "#endif // MODE_VERTEXCOLOR\n"
1618 "#ifdef MODE_FLATCOLOR\n"
1619 "#endif // MODE_FLATCOLOR\n"
1631 " color *= TintColor;\n"
1634 "#ifdef USEVERTEXTEXTUREBLEND\n"
1635 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1637 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1641 " color.rgb *= SceneBrightness;\n"
1643 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1645 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1648 "#ifdef USEDEFERREDLIGHTMAP\n"
1649 " color.rgb += deferredcolor;\n"
1652 " // 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"
1653 "#ifdef USEREFLECTION\n"
1654 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1655 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1656 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1657 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1658 " // FIXME temporary hack to detect the case that the reflection\n"
1659 " // gets blackened at edges due to leaving the area that contains actual\n"
1661 " // Remove this 'ack once we have a better way to stop this thing from\n"
1663 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1664 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1665 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1666 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1667 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1668 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1671 " gl_FragColor = vec4(color);\n"
1673 "#ifdef MODE_LIGHTSOURCE\n"
1674 "#if showshadowmap\n"
1675 "# ifdef USESHADOWMAPRECT\n"
1676 "# ifdef USESHADOWSAMPLER\n"
1677 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1679 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1682 "# ifdef USESHADOWMAP2D\n"
1683 "# ifdef USESHADOWSAMPLER\n"
1684 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1686 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1690 "# ifdef USESHADOWMAPCUBE\n"
1691 "# ifdef USESHADOWSAMPLER\n"
1692 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1694 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1698 "#endif // !MODE_LIGHTSOURCE\n"
1700 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1701 "#endif // !MODE_DEFERREDGEOMETRY\n"
1703 "#endif // FRAGMENT_SHADER\n"
1705 "#endif // !MODE_WATER\n"
1706 "#endif // !MODE_REFRACTION\n"
1707 "#endif // !MODE_BLOOMBLUR\n"
1708 "#endif // !MODE_GENERIC\n"
1709 "#endif // !MODE_POSTPROCESS\n"
1710 "#endif // !MODE_SHOWDEPTH\n"
1711 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1714 typedef struct shaderpermutationinfo_s
1716 const char *pretext;
1719 shaderpermutationinfo_t;
1721 typedef struct shadermodeinfo_s
1723 const char *vertexfilename;
1724 const char *geometryfilename;
1725 const char *fragmentfilename;
1726 const char *pretext;
1731 typedef enum shaderpermutation_e
1733 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1734 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1735 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1736 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1737 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1738 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1739 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1740 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1741 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1742 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1743 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1744 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1745 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1746 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1747 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1748 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1749 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1750 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1751 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1752 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1753 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1754 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1755 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1756 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1757 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
1758 SHADERPERMUTATION_LIMIT = 1<<25, ///< size of permutations array
1759 SHADERPERMUTATION_COUNT = 25 ///< size of shaderpermutationinfo array
1761 shaderpermutation_t;
1763 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1764 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1766 {"#define USEDIFFUSE\n", " diffuse"},
1767 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1768 {"#define USEVIEWTINT\n", " viewtint"},
1769 {"#define USECOLORMAPPING\n", " colormapping"},
1770 {"#define USESATURATION\n", " saturation"},
1771 {"#define USEFOGINSIDE\n", " foginside"},
1772 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1773 {"#define USEGAMMARAMPS\n", " gammaramps"},
1774 {"#define USECUBEFILTER\n", " cubefilter"},
1775 {"#define USEGLOW\n", " glow"},
1776 {"#define USEBLOOM\n", " bloom"},
1777 {"#define USESPECULAR\n", " specular"},
1778 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1779 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1780 {"#define USEREFLECTION\n", " reflection"},
1781 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1782 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1783 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1784 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1785 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1786 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1787 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1788 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1789 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1790 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
1793 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1794 typedef enum shadermode_e
1796 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1797 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1798 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1799 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1800 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1801 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1802 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1803 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1804 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1805 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1806 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1807 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1808 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1809 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
1810 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
1815 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1816 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1818 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1819 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1820 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1821 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1822 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1823 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1824 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1825 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1826 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1827 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1828 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1829 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1830 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1831 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1832 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1835 struct r_glsl_permutation_s;
1836 typedef struct r_glsl_permutation_s
1838 /// hash lookup data
1839 struct r_glsl_permutation_s *hashnext;
1841 unsigned int permutation;
1843 /// indicates if we have tried compiling this permutation already
1845 /// 0 if compilation failed
1847 /// locations of detected uniforms in program object, or -1 if not found
1848 int loc_Texture_First;
1849 int loc_Texture_Second;
1850 int loc_Texture_GammaRamps;
1851 int loc_Texture_Normal;
1852 int loc_Texture_Color;
1853 int loc_Texture_Gloss;
1854 int loc_Texture_Glow;
1855 int loc_Texture_SecondaryNormal;
1856 int loc_Texture_SecondaryColor;
1857 int loc_Texture_SecondaryGloss;
1858 int loc_Texture_SecondaryGlow;
1859 int loc_Texture_Pants;
1860 int loc_Texture_Shirt;
1861 int loc_Texture_FogMask;
1862 int loc_Texture_Lightmap;
1863 int loc_Texture_Deluxemap;
1864 int loc_Texture_Attenuation;
1865 int loc_Texture_Cube;
1866 int loc_Texture_Refraction;
1867 int loc_Texture_Reflection;
1868 int loc_Texture_ShadowMapRect;
1869 int loc_Texture_ShadowMapCube;
1870 int loc_Texture_ShadowMap2D;
1871 int loc_Texture_CubeProjection;
1872 int loc_Texture_ScreenDepth;
1873 int loc_Texture_ScreenNormalMap;
1874 int loc_Texture_ScreenDiffuse;
1875 int loc_Texture_ScreenSpecular;
1877 int loc_LightPosition;
1878 int loc_EyePosition;
1879 int loc_Color_Pants;
1880 int loc_Color_Shirt;
1882 int loc_FogPlaneViewDist;
1883 int loc_FogRangeRecip;
1884 int loc_FogHeightFade;
1885 int loc_AmbientScale;
1886 int loc_DiffuseScale;
1887 int loc_SpecularScale;
1888 int loc_SpecularPower;
1890 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1891 int loc_OffsetMapping_Scale;
1893 int loc_AmbientColor;
1894 int loc_DiffuseColor;
1895 int loc_SpecularColor;
1897 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1898 int loc_GammaCoeff; ///< 1 / gamma
1899 int loc_DistortScaleRefractReflect;
1900 int loc_ScreenScaleRefractReflect;
1901 int loc_ScreenCenterRefractReflect;
1902 int loc_RefractColor;
1903 int loc_ReflectColor;
1904 int loc_ReflectFactor;
1905 int loc_ReflectOffset;
1913 int loc_ShadowMap_TextureScale;
1914 int loc_ShadowMap_Parameters;
1915 int loc_ScreenToDepth;
1916 int loc_ViewToLight;
1917 int loc_DeferredDiffuseRange;
1918 int loc_DeferredSpecularRange;
1920 r_glsl_permutation_t;
1922 #define SHADERPERMUTATION_HASHSIZE 256
1924 /// information about each possible shader permutation
1925 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1926 /// currently selected permutation
1927 r_glsl_permutation_t *r_glsl_permutation;
1928 /// storage for permutations linked in the hash table
1929 memexpandablearray_t r_glsl_permutationarray;
1931 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1933 //unsigned int hashdepth = 0;
1934 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1935 r_glsl_permutation_t *p;
1936 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1938 if (p->mode == mode && p->permutation == permutation)
1940 //if (hashdepth > 10)
1941 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1946 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1948 p->permutation = permutation;
1949 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1950 r_glsl_permutationhash[mode][hashindex] = p;
1951 //if (hashdepth > 10)
1952 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1956 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1959 if (!filename || !filename[0])
1961 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1964 if (printfromdisknotice)
1965 Con_DPrintf("from disk %s... ", filename);
1966 return shaderstring;
1968 else if (!strcmp(filename, "glsl/default.glsl"))
1970 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1971 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1973 return shaderstring;
1976 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1979 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1980 int vertstrings_count = 0;
1981 int geomstrings_count = 0;
1982 int fragstrings_count = 0;
1983 char *vertexstring, *geometrystring, *fragmentstring;
1984 const char *vertstrings_list[32+3];
1985 const char *geomstrings_list[32+3];
1986 const char *fragstrings_list[32+3];
1987 char permutationname[256];
1994 permutationname[0] = 0;
1995 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1996 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1997 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1999 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
2001 // the first pretext is which type of shader to compile as
2002 // (later these will all be bound together as a program object)
2003 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
2004 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
2005 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
2007 // the second pretext is the mode (for example a light source)
2008 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
2009 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
2010 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
2011 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
2013 // now add all the permutation pretexts
2014 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2016 if (permutation & (1<<i))
2018 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
2019 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
2020 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
2021 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
2025 // keep line numbers correct
2026 vertstrings_list[vertstrings_count++] = "\n";
2027 geomstrings_list[geomstrings_count++] = "\n";
2028 fragstrings_list[fragstrings_count++] = "\n";
2032 // now append the shader text itself
2033 vertstrings_list[vertstrings_count++] = vertexstring;
2034 geomstrings_list[geomstrings_count++] = geometrystring;
2035 fragstrings_list[fragstrings_count++] = fragmentstring;
2037 // if any sources were NULL, clear the respective list
2039 vertstrings_count = 0;
2040 if (!geometrystring)
2041 geomstrings_count = 0;
2042 if (!fragmentstring)
2043 fragstrings_count = 0;
2045 // compile the shader program
2046 if (vertstrings_count + geomstrings_count + fragstrings_count)
2047 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
2051 qglUseProgramObjectARB(p->program);CHECKGLERROR
2052 // look up all the uniform variable names we care about, so we don't
2053 // have to look them up every time we set them
2054 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
2055 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
2056 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
2057 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
2058 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
2059 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
2060 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
2061 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
2062 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
2063 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
2064 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
2065 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
2066 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
2067 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
2068 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
2069 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
2070 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
2071 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
2072 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
2073 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
2074 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
2075 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
2076 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
2077 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
2078 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
2079 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
2080 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
2081 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
2082 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
2083 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
2084 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
2085 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
2086 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
2087 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
2088 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
2089 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
2090 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
2091 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
2092 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
2093 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
2094 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
2095 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
2096 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
2097 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
2098 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
2099 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
2100 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
2101 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
2102 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
2103 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
2104 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
2105 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
2106 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
2107 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
2108 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
2109 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
2110 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
2111 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
2112 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
2113 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
2114 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
2115 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
2116 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
2117 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
2118 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
2119 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
2120 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
2121 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
2122 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
2123 p->loc_DeferredDiffuseRange = qglGetUniformLocationARB(p->program, "DeferredDiffuseRange");
2124 p->loc_DeferredSpecularRange = qglGetUniformLocationARB(p->program, "DeferredSpecularRange");
2125 // initialize the samplers to refer to the texture units we use
2126 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
2127 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
2128 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
2129 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
2130 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
2131 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
2132 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
2133 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
2134 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
2135 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
2136 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
2137 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
2138 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
2139 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
2140 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
2141 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
2142 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
2143 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
2144 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
2145 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
2146 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
2147 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
2148 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
2149 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
2150 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
2151 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
2152 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
2153 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
2155 if (developer.integer)
2156 Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
2159 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
2163 Mem_Free(vertexstring);
2165 Mem_Free(geometrystring);
2167 Mem_Free(fragmentstring);
2170 void R_GLSL_Restart_f(void)
2172 unsigned int i, limit;
2173 r_glsl_permutation_t *p;
2174 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
2175 for (i = 0;i < limit;i++)
2177 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
2179 GL_Backend_FreeProgram(p->program);
2180 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
2183 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2186 void R_GLSL_DumpShader_f(void)
2190 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
2193 Con_Printf("failed to write to glsl/default.glsl\n");
2197 FS_Print(file, "/* The engine may define the following macros:\n");
2198 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2199 for (i = 0;i < SHADERMODE_COUNT;i++)
2200 FS_Print(file, shadermodeinfo[i].pretext);
2201 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2202 FS_Print(file, shaderpermutationinfo[i].pretext);
2203 FS_Print(file, "*/\n");
2204 FS_Print(file, builtinshaderstring);
2207 Con_Printf("glsl/default.glsl written\n");
2210 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
2212 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2213 if (r_glsl_permutation != perm)
2215 r_glsl_permutation = perm;
2216 if (!r_glsl_permutation->program)
2218 if (!r_glsl_permutation->compiled)
2219 R_GLSL_CompilePermutation(perm, mode, permutation);
2220 if (!r_glsl_permutation->program)
2222 // remove features until we find a valid permutation
2224 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2226 // reduce i more quickly whenever it would not remove any bits
2227 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2228 if (!(permutation & j))
2231 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2232 if (!r_glsl_permutation->compiled)
2233 R_GLSL_CompilePermutation(perm, mode, permutation);
2234 if (r_glsl_permutation->program)
2237 if (i >= SHADERPERMUTATION_COUNT)
2239 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2240 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2241 qglUseProgramObjectARB(0);CHECKGLERROR
2242 return; // no bit left to clear, entire mode is broken
2247 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2251 void R_SetupGenericShader(qboolean usetexture)
2253 switch(vid.renderpath)
2255 case RENDERPATH_GL20:
2256 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2258 case RENDERPATH_GL13:
2259 case RENDERPATH_GL11:
2264 void R_SetupGenericTwoTextureShader(int texturemode)
2266 switch (vid.renderpath)
2268 case RENDERPATH_GL20:
2269 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))));
2271 case RENDERPATH_GL13:
2272 case RENDERPATH_GL11:
2273 R_Mesh_TexCombine(1, GL_DECAL, GL_DECAL, 1, 1);
2278 void R_SetupDepthOrShadowShader(void)
2280 switch (vid.renderpath)
2282 case RENDERPATH_GL20:
2283 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2285 case RENDERPATH_GL13:
2287 case RENDERPATH_GL11:
2292 void R_SetupShowDepthShader(void)
2294 switch (vid.renderpath)
2296 case RENDERPATH_GL20:
2297 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2299 case RENDERPATH_GL13:
2301 case RENDERPATH_GL11:
2306 extern qboolean r_shadow_usingdeferredprepass;
2307 extern cvar_t r_shadow_deferred_8bitrange;
2308 extern rtexture_t *r_shadow_attenuationgradienttexture;
2309 extern rtexture_t *r_shadow_attenuation2dtexture;
2310 extern rtexture_t *r_shadow_attenuation3dtexture;
2311 extern qboolean r_shadow_usingshadowmaprect;
2312 extern qboolean r_shadow_usingshadowmapcube;
2313 extern qboolean r_shadow_usingshadowmap2d;
2314 extern float r_shadow_shadowmap_texturescale[2];
2315 extern float r_shadow_shadowmap_parameters[4];
2316 extern qboolean r_shadow_shadowmapvsdct;
2317 extern qboolean r_shadow_shadowmapsampler;
2318 extern int r_shadow_shadowmappcf;
2319 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2321 // select a permutation of the lighting shader appropriate to this
2322 // combination of texture, entity, light source, and fogging, only use the
2323 // minimum features necessary to avoid wasting rendering time in the
2324 // fragment shader on features that are not being used
2325 unsigned int permutation = 0;
2326 unsigned int mode = 0;
2327 // TODO: implement geometry-shader based shadow volumes someday
2328 if (r_glsl_offsetmapping.integer)
2330 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2331 if (r_glsl_offsetmapping_reliefmapping.integer)
2332 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2334 if (rsurfacepass == RSURFPASS_BACKGROUND)
2336 // distorted background
2337 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2338 mode = SHADERMODE_WATER;
2340 mode = SHADERMODE_REFRACTION;
2342 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2344 // normalmap (deferred prepass), may use alpha test on diffuse
2345 mode = SHADERMODE_DEFERREDGEOMETRY;
2346 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2347 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2348 if (r_refdef.fogenabled)
2349 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2350 if (r_glsl_offsetmapping.integer)
2352 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2353 if (r_glsl_offsetmapping_reliefmapping.integer)
2354 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2357 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2360 mode = r_shadow_usingdeferredprepass ? SHADERMODE_DEFERREDLIGHTSOURCE : SHADERMODE_LIGHTSOURCE;
2361 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2362 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2363 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2364 permutation |= SHADERPERMUTATION_CUBEFILTER;
2365 if (diffusescale > 0)
2366 permutation |= SHADERPERMUTATION_DIFFUSE;
2367 if (specularscale > 0)
2368 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2369 if (r_refdef.fogenabled)
2370 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2371 if (rsurface.texture->colormapping)
2372 permutation |= SHADERPERMUTATION_COLORMAPPING;
2373 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2375 if (r_shadow_usingshadowmaprect)
2376 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2377 if (r_shadow_usingshadowmap2d)
2378 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2379 if (r_shadow_usingshadowmapcube)
2380 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2381 else if(r_shadow_shadowmapvsdct)
2382 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2384 if (r_shadow_shadowmapsampler)
2385 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2386 if (r_shadow_shadowmappcf > 1)
2387 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2388 else if (r_shadow_shadowmappcf)
2389 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2392 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2394 // unshaded geometry (fullbright or ambient model lighting)
2395 mode = SHADERMODE_FLATCOLOR;
2396 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2397 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2398 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2399 permutation |= SHADERPERMUTATION_GLOW;
2400 if (r_refdef.fogenabled)
2401 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2402 if (rsurface.texture->colormapping)
2403 permutation |= SHADERPERMUTATION_COLORMAPPING;
2404 if (r_glsl_offsetmapping.integer)
2406 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2407 if (r_glsl_offsetmapping_reliefmapping.integer)
2408 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2410 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2411 permutation |= SHADERPERMUTATION_REFLECTION;
2413 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2415 // directional model lighting
2416 mode = SHADERMODE_LIGHTDIRECTION;
2417 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2418 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2419 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2420 permutation |= SHADERPERMUTATION_GLOW;
2421 permutation |= SHADERPERMUTATION_DIFFUSE;
2422 if (specularscale > 0)
2423 permutation |= SHADERPERMUTATION_SPECULAR;
2424 if (r_refdef.fogenabled)
2425 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2426 if (rsurface.texture->colormapping)
2427 permutation |= SHADERPERMUTATION_COLORMAPPING;
2428 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2429 permutation |= SHADERPERMUTATION_REFLECTION;
2430 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2431 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2433 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2435 // ambient model lighting
2436 mode = SHADERMODE_LIGHTDIRECTION;
2437 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2438 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2439 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2440 permutation |= SHADERPERMUTATION_GLOW;
2441 if (r_refdef.fogenabled)
2442 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2443 if (rsurface.texture->colormapping)
2444 permutation |= SHADERPERMUTATION_COLORMAPPING;
2445 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2446 permutation |= SHADERPERMUTATION_REFLECTION;
2447 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2448 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2453 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2455 // deluxemapping (light direction texture)
2456 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2457 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2459 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2460 permutation |= SHADERPERMUTATION_DIFFUSE;
2461 if (specularscale > 0)
2462 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2464 else if (r_glsl_deluxemapping.integer >= 2)
2466 // fake deluxemapping (uniform light direction in tangentspace)
2467 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2468 permutation |= SHADERPERMUTATION_DIFFUSE;
2469 if (specularscale > 0)
2470 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2472 else if (rsurface.uselightmaptexture)
2474 // ordinary lightmapping (q1bsp, q3bsp)
2475 mode = SHADERMODE_LIGHTMAP;
2479 // ordinary vertex coloring (q3bsp)
2480 mode = SHADERMODE_VERTEXCOLOR;
2482 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2483 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2484 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2485 permutation |= SHADERPERMUTATION_GLOW;
2486 if (r_refdef.fogenabled)
2487 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2488 if (rsurface.texture->colormapping)
2489 permutation |= SHADERPERMUTATION_COLORMAPPING;
2490 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2491 permutation |= SHADERPERMUTATION_REFLECTION;
2492 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2493 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2495 if(permutation & SHADERPERMUTATION_SPECULAR)
2496 if(r_shadow_glossexact.integer)
2497 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2498 R_SetupShader_SetPermutation(mode, permutation);
2499 if (mode == SHADERMODE_DEFERREDLIGHTSOURCE)
2501 // this is the location of the light in view space
2502 vec3_t viewlightorigin;
2503 // this transforms from view space (camera) to light space (cubemap)
2504 matrix4x4_t viewtolight;
2505 matrix4x4_t lighttoview;
2506 float viewtolight16f[16];
2507 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rsurface.rtlight->shadoworigin, viewlightorigin);
2508 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rsurface.rtlight->matrix_lighttoworld);
2509 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2510 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2511 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2512 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight, 1, false, viewtolight16f);
2513 if (permutation & SHADERPERMUTATION_DIFFUSE)
2515 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2516 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2517 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2518 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2522 // ambient only is simpler
2523 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]);
2524 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2525 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2526 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2528 // additive passes are only darkened by fog, not tinted
2529 if (r_glsl_permutation->loc_FogColor >= 0)
2530 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2531 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]);
2532 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]);
2533 if (r_glsl_permutation->loc_DeferredDiffuseRange >= 0) qglUniform1fARB(r_glsl_permutation->loc_DeferredDiffuseRange, 1.0f / r_shadow_deferred_8bitrange.value);
2534 if (r_glsl_permutation->loc_DeferredSpecularRange >= 0) qglUniform1fARB(r_glsl_permutation->loc_DeferredSpecularRange, 1.0f / r_shadow_deferred_8bitrange.value);
2536 else if (mode == SHADERMODE_LIGHTSOURCE)
2538 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2539 if (permutation & SHADERPERMUTATION_DIFFUSE)
2541 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2542 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2543 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2544 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2548 // ambient only is simpler
2549 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]);
2550 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2551 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2552 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2554 // additive passes are only darkened by fog, not tinted
2555 if (r_glsl_permutation->loc_FogColor >= 0)
2556 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2557 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]);
2558 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]);
2562 if (mode == SHADERMODE_LIGHTDIRECTION)
2564 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);
2565 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);
2566 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);
2567 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]);
2571 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2572 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2573 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2575 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]);
2576 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);
2577 // additive passes are only darkened by fog, not tinted
2578 if (r_glsl_permutation->loc_FogColor >= 0)
2580 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2581 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2583 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2585 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);
2586 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]);
2587 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]);
2588 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2589 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2590 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2591 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2592 if (r_glsl_permutation->loc_DeferredDiffuseRange >= 0) qglUniform1fARB(r_glsl_permutation->loc_DeferredDiffuseRange, r_shadow_deferred_8bitrange.value * r_refdef.view.colorscale);
2593 if (r_glsl_permutation->loc_DeferredSpecularRange >= 0) qglUniform1fARB(r_glsl_permutation->loc_DeferredSpecularRange, r_shadow_deferred_8bitrange.value * r_refdef.view.colorscale * specularscale);
2595 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2596 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2597 if (r_glsl_permutation->loc_Color_Pants >= 0)
2599 if (rsurface.texture->currentskinframe->pants)
2600 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2602 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2604 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2606 if (rsurface.texture->currentskinframe->shirt)
2607 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2609 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2611 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]);
2612 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2613 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2614 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2615 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2617 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2621 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2623 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2624 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2628 #define SKINFRAME_HASH 1024
2632 int loadsequence; // incremented each level change
2633 memexpandablearray_t array;
2634 skinframe_t *hash[SKINFRAME_HASH];
2637 r_skinframe_t r_skinframe;
2639 void R_SkinFrame_PrepareForPurge(void)
2641 r_skinframe.loadsequence++;
2642 // wrap it without hitting zero
2643 if (r_skinframe.loadsequence >= 200)
2644 r_skinframe.loadsequence = 1;
2647 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2651 // mark the skinframe as used for the purging code
2652 skinframe->loadsequence = r_skinframe.loadsequence;
2655 void R_SkinFrame_Purge(void)
2659 for (i = 0;i < SKINFRAME_HASH;i++)
2661 for (s = r_skinframe.hash[i];s;s = s->next)
2663 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2665 if (s->merged == s->base)
2667 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2668 R_PurgeTexture(s->stain );s->stain = NULL;
2669 R_PurgeTexture(s->merged);s->merged = NULL;
2670 R_PurgeTexture(s->base );s->base = NULL;
2671 R_PurgeTexture(s->pants );s->pants = NULL;
2672 R_PurgeTexture(s->shirt );s->shirt = NULL;
2673 R_PurgeTexture(s->nmap );s->nmap = NULL;
2674 R_PurgeTexture(s->gloss );s->gloss = NULL;
2675 R_PurgeTexture(s->glow );s->glow = NULL;
2676 R_PurgeTexture(s->fog );s->fog = NULL;
2677 s->loadsequence = 0;
2683 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2685 char basename[MAX_QPATH];
2687 Image_StripImageExtension(name, basename, sizeof(basename));
2689 if( last == NULL ) {
2691 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2692 item = r_skinframe.hash[hashindex];
2697 // linearly search through the hash bucket
2698 for( ; item ; item = item->next ) {
2699 if( !strcmp( item->basename, basename ) ) {
2706 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2710 char basename[MAX_QPATH];
2712 Image_StripImageExtension(name, basename, sizeof(basename));
2714 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2715 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2716 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2720 rtexture_t *dyntexture;
2721 // check whether its a dynamic texture
2722 dyntexture = CL_GetDynTexture( basename );
2723 if (!add && !dyntexture)
2725 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2726 memset(item, 0, sizeof(*item));
2727 strlcpy(item->basename, basename, sizeof(item->basename));
2728 item->base = dyntexture; // either NULL or dyntexture handle
2729 item->textureflags = textureflags;
2730 item->comparewidth = comparewidth;
2731 item->compareheight = compareheight;
2732 item->comparecrc = comparecrc;
2733 item->next = r_skinframe.hash[hashindex];
2734 r_skinframe.hash[hashindex] = item;
2736 else if( item->base == NULL )
2738 rtexture_t *dyntexture;
2739 // check whether its a dynamic texture
2740 // 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]
2741 dyntexture = CL_GetDynTexture( basename );
2742 item->base = dyntexture; // either NULL or dyntexture handle
2745 R_SkinFrame_MarkUsed(item);
2749 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2751 unsigned long long avgcolor[5], wsum; \
2759 for(pix = 0; pix < cnt; ++pix) \
2762 for(comp = 0; comp < 3; ++comp) \
2764 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2767 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2769 for(comp = 0; comp < 3; ++comp) \
2770 avgcolor[comp] += getpixel * w; \
2773 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2774 avgcolor[4] += getpixel; \
2776 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2778 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2779 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2780 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2781 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2784 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2787 unsigned char *pixels;
2788 unsigned char *bumppixels;
2789 unsigned char *basepixels = NULL;
2790 int basepixels_width;
2791 int basepixels_height;
2792 skinframe_t *skinframe;
2794 if (cls.state == ca_dedicated)
2797 // return an existing skinframe if already loaded
2798 // if loading of the first image fails, don't make a new skinframe as it
2799 // would cause all future lookups of this to be missing
2800 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2801 if (skinframe && skinframe->base)
2804 basepixels = loadimagepixelsbgra(name, complain, true);
2805 if (basepixels == NULL)
2808 if (developer_loading.integer)
2809 Con_Printf("loading skin \"%s\"\n", name);
2811 // we've got some pixels to store, so really allocate this new texture now
2813 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2814 skinframe->stain = NULL;
2815 skinframe->merged = NULL;
2816 skinframe->base = r_texture_notexture;
2817 skinframe->pants = NULL;
2818 skinframe->shirt = NULL;
2819 skinframe->nmap = r_texture_blanknormalmap;
2820 skinframe->gloss = NULL;
2821 skinframe->glow = NULL;
2822 skinframe->fog = NULL;
2823 skinframe->hasalpha = false;
2825 basepixels_width = image_width;
2826 basepixels_height = image_height;
2827 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);
2829 if (textureflags & TEXF_ALPHA)
2831 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2833 if (basepixels[j] < 255)
2835 skinframe->hasalpha = true;
2839 if (r_loadfog && skinframe->hasalpha)
2841 // has transparent pixels
2842 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2843 for (j = 0;j < image_width * image_height * 4;j += 4)
2848 pixels[j+3] = basepixels[j+3];
2850 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);
2855 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2856 //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]);
2858 // _norm is the name used by tenebrae and has been adopted as standard
2859 if (r_loadnormalmap)
2861 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2863 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);
2867 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2869 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2870 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2871 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);
2873 Mem_Free(bumppixels);
2875 else if (r_shadow_bumpscale_basetexture.value > 0)
2877 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2878 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2879 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);
2883 // _luma is supported for tenebrae compatibility
2884 // (I think it's a very stupid name, but oh well)
2885 // _glow is the preferred name
2886 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;}
2887 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;}
2888 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;}
2889 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;}
2892 Mem_Free(basepixels);
2897 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2898 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2901 unsigned char *temp1, *temp2;
2902 skinframe_t *skinframe;
2904 if (cls.state == ca_dedicated)
2907 // if already loaded just return it, otherwise make a new skinframe
2908 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2909 if (skinframe && skinframe->base)
2912 skinframe->stain = NULL;
2913 skinframe->merged = NULL;
2914 skinframe->base = r_texture_notexture;
2915 skinframe->pants = NULL;
2916 skinframe->shirt = NULL;
2917 skinframe->nmap = r_texture_blanknormalmap;
2918 skinframe->gloss = NULL;
2919 skinframe->glow = NULL;
2920 skinframe->fog = NULL;
2921 skinframe->hasalpha = false;
2923 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2927 if (developer_loading.integer)
2928 Con_Printf("loading 32bit skin \"%s\"\n", name);
2930 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2932 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2933 temp2 = temp1 + width * height * 4;
2934 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2935 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2938 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2939 if (textureflags & TEXF_ALPHA)
2941 for (i = 3;i < width * height * 4;i += 4)
2943 if (skindata[i] < 255)
2945 skinframe->hasalpha = true;
2949 if (r_loadfog && skinframe->hasalpha)
2951 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2952 memcpy(fogpixels, skindata, width * height * 4);
2953 for (i = 0;i < width * height * 4;i += 4)
2954 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2955 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2956 Mem_Free(fogpixels);
2960 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2961 //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]);
2966 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2970 skinframe_t *skinframe;
2972 if (cls.state == ca_dedicated)
2975 // if already loaded just return it, otherwise make a new skinframe
2976 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2977 if (skinframe && skinframe->base)
2980 skinframe->stain = NULL;
2981 skinframe->merged = NULL;
2982 skinframe->base = r_texture_notexture;
2983 skinframe->pants = NULL;
2984 skinframe->shirt = NULL;
2985 skinframe->nmap = r_texture_blanknormalmap;
2986 skinframe->gloss = NULL;
2987 skinframe->glow = NULL;
2988 skinframe->fog = NULL;
2989 skinframe->hasalpha = false;
2991 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2995 if (developer_loading.integer)
2996 Con_Printf("loading quake skin \"%s\"\n", name);
2998 // 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)
2999 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
3000 memcpy(skinframe->qpixels, skindata, width*height);
3001 skinframe->qwidth = width;
3002 skinframe->qheight = height;
3005 for (i = 0;i < width * height;i++)
3006 featuresmask |= palette_featureflags[skindata[i]];
3008 skinframe->hasalpha = false;
3009 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3010 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3011 skinframe->qgeneratemerged = true;
3012 skinframe->qgeneratebase = skinframe->qhascolormapping;
3013 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3015 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3016 //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]);
3021 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3025 unsigned char *skindata;
3027 if (!skinframe->qpixels)
3030 if (!skinframe->qhascolormapping)
3031 colormapped = false;
3035 if (!skinframe->qgeneratebase)
3040 if (!skinframe->qgeneratemerged)
3044 width = skinframe->qwidth;
3045 height = skinframe->qheight;
3046 skindata = skinframe->qpixels;
3048 if (skinframe->qgeneratenmap)
3050 unsigned char *temp1, *temp2;
3051 skinframe->qgeneratenmap = false;
3052 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3053 temp2 = temp1 + width * height * 4;
3054 // use either a custom palette or the quake palette
3055 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3056 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3057 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
3061 if (skinframe->qgenerateglow)
3063 skinframe->qgenerateglow = false;
3064 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
3069 skinframe->qgeneratebase = false;
3070 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);
3071 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
3072 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
3076 skinframe->qgeneratemerged = false;
3077 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3080 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3082 Mem_Free(skinframe->qpixels);
3083 skinframe->qpixels = NULL;
3087 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)
3090 skinframe_t *skinframe;
3092 if (cls.state == ca_dedicated)
3095 // if already loaded just return it, otherwise make a new skinframe
3096 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3097 if (skinframe && skinframe->base)
3100 skinframe->stain = NULL;
3101 skinframe->merged = NULL;
3102 skinframe->base = r_texture_notexture;
3103 skinframe->pants = NULL;
3104 skinframe->shirt = NULL;
3105 skinframe->nmap = r_texture_blanknormalmap;
3106 skinframe->gloss = NULL;
3107 skinframe->glow = NULL;
3108 skinframe->fog = NULL;
3109 skinframe->hasalpha = false;
3111 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3115 if (developer_loading.integer)
3116 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3118 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
3119 if (textureflags & TEXF_ALPHA)
3121 for (i = 0;i < width * height;i++)
3123 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3125 skinframe->hasalpha = true;
3129 if (r_loadfog && skinframe->hasalpha)
3130 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
3133 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3134 //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]);
3139 skinframe_t *R_SkinFrame_LoadMissing(void)
3141 skinframe_t *skinframe;
3143 if (cls.state == ca_dedicated)
3146 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
3147 skinframe->stain = NULL;
3148 skinframe->merged = NULL;
3149 skinframe->base = r_texture_notexture;
3150 skinframe->pants = NULL;
3151 skinframe->shirt = NULL;
3152 skinframe->nmap = r_texture_blanknormalmap;
3153 skinframe->gloss = NULL;
3154 skinframe->glow = NULL;
3155 skinframe->fog = NULL;
3156 skinframe->hasalpha = false;
3158 skinframe->avgcolor[0] = rand() / RAND_MAX;
3159 skinframe->avgcolor[1] = rand() / RAND_MAX;
3160 skinframe->avgcolor[2] = rand() / RAND_MAX;
3161 skinframe->avgcolor[3] = 1;
3166 void R_Main_FreeViewCache(void)
3168 if (r_refdef.viewcache.entityvisible)
3169 Mem_Free(r_refdef.viewcache.entityvisible);
3170 if (r_refdef.viewcache.world_pvsbits)
3171 Mem_Free(r_refdef.viewcache.world_pvsbits);
3172 if (r_refdef.viewcache.world_leafvisible)
3173 Mem_Free(r_refdef.viewcache.world_leafvisible);
3174 if (r_refdef.viewcache.world_surfacevisible)
3175 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3176 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3179 void R_Main_ResizeViewCache(void)
3181 int numentities = r_refdef.scene.numentities;
3182 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3183 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3184 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3185 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3186 if (r_refdef.viewcache.maxentities < numentities)
3188 r_refdef.viewcache.maxentities = numentities;
3189 if (r_refdef.viewcache.entityvisible)
3190 Mem_Free(r_refdef.viewcache.entityvisible);
3191 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3193 if (r_refdef.viewcache.world_numclusters != numclusters)
3195 r_refdef.viewcache.world_numclusters = numclusters;
3196 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3197 if (r_refdef.viewcache.world_pvsbits)
3198 Mem_Free(r_refdef.viewcache.world_pvsbits);
3199 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3201 if (r_refdef.viewcache.world_numleafs != numleafs)
3203 r_refdef.viewcache.world_numleafs = numleafs;
3204 if (r_refdef.viewcache.world_leafvisible)
3205 Mem_Free(r_refdef.viewcache.world_leafvisible);
3206 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3208 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3210 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3211 if (r_refdef.viewcache.world_surfacevisible)
3212 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3213 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3217 extern rtexture_t *loadingscreentexture;
3218 void gl_main_start(void)
3220 loadingscreentexture = NULL;
3221 r_texture_blanknormalmap = NULL;
3222 r_texture_white = NULL;
3223 r_texture_grey128 = NULL;
3224 r_texture_black = NULL;
3225 r_texture_whitecube = NULL;
3226 r_texture_normalizationcube = NULL;
3227 r_texture_fogattenuation = NULL;
3228 r_texture_gammaramps = NULL;
3230 switch(vid.renderpath)
3232 case RENDERPATH_GL20:
3233 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3234 Cvar_SetValueQuick(&gl_combine, 1);
3235 Cvar_SetValueQuick(&r_glsl, 1);
3236 r_loadnormalmap = true;
3240 case RENDERPATH_GL13:
3241 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3242 Cvar_SetValueQuick(&gl_combine, 1);
3243 Cvar_SetValueQuick(&r_glsl, 0);
3244 r_loadnormalmap = false;
3245 r_loadgloss = false;
3248 case RENDERPATH_GL11:
3249 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3250 Cvar_SetValueQuick(&gl_combine, 0);
3251 Cvar_SetValueQuick(&r_glsl, 0);
3252 r_loadnormalmap = false;
3253 r_loadgloss = false;
3259 R_FrameData_Reset();
3263 memset(r_queries, 0, sizeof(r_queries));
3265 r_qwskincache = NULL;
3266 r_qwskincache_size = 0;
3268 // set up r_skinframe loading system for textures
3269 memset(&r_skinframe, 0, sizeof(r_skinframe));
3270 r_skinframe.loadsequence = 1;
3271 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3273 r_main_texturepool = R_AllocTexturePool();
3274 R_BuildBlankTextures();
3276 if (vid.support.arb_texture_cube_map)
3279 R_BuildNormalizationCube();
3281 r_texture_fogattenuation = NULL;
3282 r_texture_gammaramps = NULL;
3283 //r_texture_fogintensity = NULL;
3284 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3285 memset(&r_waterstate, 0, sizeof(r_waterstate));
3286 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3287 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3288 memset(&r_svbsp, 0, sizeof (r_svbsp));
3290 r_refdef.fogmasktable_density = 0;
3293 void gl_main_shutdown(void)
3296 R_FrameData_Reset();
3298 R_Main_FreeViewCache();
3301 qglDeleteQueriesARB(r_maxqueries, r_queries);
3305 memset(r_queries, 0, sizeof(r_queries));
3307 r_qwskincache = NULL;
3308 r_qwskincache_size = 0;
3310 // clear out the r_skinframe state
3311 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3312 memset(&r_skinframe, 0, sizeof(r_skinframe));
3315 Mem_Free(r_svbsp.nodes);
3316 memset(&r_svbsp, 0, sizeof (r_svbsp));
3317 R_FreeTexturePool(&r_main_texturepool);
3318 loadingscreentexture = NULL;
3319 r_texture_blanknormalmap = NULL;
3320 r_texture_white = NULL;
3321 r_texture_grey128 = NULL;
3322 r_texture_black = NULL;
3323 r_texture_whitecube = NULL;
3324 r_texture_normalizationcube = NULL;
3325 r_texture_fogattenuation = NULL;
3326 r_texture_gammaramps = NULL;
3327 //r_texture_fogintensity = NULL;
3328 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3329 memset(&r_waterstate, 0, sizeof(r_waterstate));
3333 extern void CL_ParseEntityLump(char *entitystring);
3334 void gl_main_newmap(void)
3336 // FIXME: move this code to client
3338 char *entities, entname[MAX_QPATH];
3340 Mem_Free(r_qwskincache);
3341 r_qwskincache = NULL;
3342 r_qwskincache_size = 0;
3345 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
3346 l = (int)strlen(entname) - 4;
3347 if (l >= 0 && !strcmp(entname + l, ".bsp"))
3349 memcpy(entname + l, ".ent", 5);
3350 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3352 CL_ParseEntityLump(entities);
3357 if (cl.worldmodel->brush.entities)
3358 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3360 R_Main_FreeViewCache();
3362 R_FrameData_Reset();
3365 void GL_Main_Init(void)
3367 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3369 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3370 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3371 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3372 if (gamemode == GAME_NEHAHRA)
3374 Cvar_RegisterVariable (&gl_fogenable);
3375 Cvar_RegisterVariable (&gl_fogdensity);
3376 Cvar_RegisterVariable (&gl_fogred);
3377 Cvar_RegisterVariable (&gl_foggreen);
3378 Cvar_RegisterVariable (&gl_fogblue);
3379 Cvar_RegisterVariable (&gl_fogstart);
3380 Cvar_RegisterVariable (&gl_fogend);
3381 Cvar_RegisterVariable (&gl_skyclip);
3383 Cvar_RegisterVariable(&r_motionblur);
3384 Cvar_RegisterVariable(&r_motionblur_maxblur);
3385 Cvar_RegisterVariable(&r_motionblur_bmin);
3386 Cvar_RegisterVariable(&r_motionblur_vmin);
3387 Cvar_RegisterVariable(&r_motionblur_vmax);
3388 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3389 Cvar_RegisterVariable(&r_motionblur_randomize);
3390 Cvar_RegisterVariable(&r_damageblur);
3391 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3392 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3393 Cvar_RegisterVariable(&r_equalize_entities_by);
3394 Cvar_RegisterVariable(&r_equalize_entities_to);
3395 Cvar_RegisterVariable(&r_depthfirst);
3396 Cvar_RegisterVariable(&r_useinfinitefarclip);
3397 Cvar_RegisterVariable(&r_farclip_base);
3398 Cvar_RegisterVariable(&r_farclip_world);
3399 Cvar_RegisterVariable(&r_nearclip);
3400 Cvar_RegisterVariable(&r_showbboxes);
3401 Cvar_RegisterVariable(&r_showsurfaces);
3402 Cvar_RegisterVariable(&r_showtris);
3403 Cvar_RegisterVariable(&r_shownormals);
3404 Cvar_RegisterVariable(&r_showlighting);
3405 Cvar_RegisterVariable(&r_showshadowvolumes);
3406 Cvar_RegisterVariable(&r_showcollisionbrushes);
3407 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3408 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3409 Cvar_RegisterVariable(&r_showdisabledepthtest);
3410 Cvar_RegisterVariable(&r_drawportals);
3411 Cvar_RegisterVariable(&r_drawentities);
3412 Cvar_RegisterVariable(&r_cullentities_trace);
3413 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3414 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3415 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3416 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3417 Cvar_RegisterVariable(&r_drawviewmodel);
3418 Cvar_RegisterVariable(&r_speeds);
3419 Cvar_RegisterVariable(&r_fullbrights);
3420 Cvar_RegisterVariable(&r_wateralpha);
3421 Cvar_RegisterVariable(&r_dynamic);
3422 Cvar_RegisterVariable(&r_fullbright);
3423 Cvar_RegisterVariable(&r_shadows);
3424 Cvar_RegisterVariable(&r_shadows_darken);
3425 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3426 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3427 Cvar_RegisterVariable(&r_shadows_throwdistance);
3428 Cvar_RegisterVariable(&r_shadows_throwdirection);
3429 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3430 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3431 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3432 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3433 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3434 Cvar_RegisterVariable(&r_fog_exp2);
3435 Cvar_RegisterVariable(&r_drawfog);
3436 Cvar_RegisterVariable(&r_textureunits);
3437 Cvar_RegisterVariable(&gl_combine);
3438 Cvar_RegisterVariable(&r_glsl);
3439 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3440 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3441 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3442 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3443 Cvar_RegisterVariable(&r_glsl_postprocess);
3444 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3445 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3446 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3447 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3448 Cvar_RegisterVariable(&r_water);
3449 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3450 Cvar_RegisterVariable(&r_water_clippingplanebias);
3451 Cvar_RegisterVariable(&r_water_refractdistort);
3452 Cvar_RegisterVariable(&r_water_reflectdistort);
3453 Cvar_RegisterVariable(&r_lerpsprites);
3454 Cvar_RegisterVariable(&r_lerpmodels);
3455 Cvar_RegisterVariable(&r_lerplightstyles);
3456 Cvar_RegisterVariable(&r_waterscroll);
3457 Cvar_RegisterVariable(&r_bloom);
3458 Cvar_RegisterVariable(&r_bloom_colorscale);
3459 Cvar_RegisterVariable(&r_bloom_brighten);
3460 Cvar_RegisterVariable(&r_bloom_blur);
3461 Cvar_RegisterVariable(&r_bloom_resolution);
3462 Cvar_RegisterVariable(&r_bloom_colorexponent);
3463 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3464 Cvar_RegisterVariable(&r_hdr);
3465 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3466 Cvar_RegisterVariable(&r_hdr_glowintensity);
3467 Cvar_RegisterVariable(&r_hdr_range);
3468 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3469 Cvar_RegisterVariable(&developer_texturelogging);
3470 Cvar_RegisterVariable(&gl_lightmaps);
3471 Cvar_RegisterVariable(&r_test);
3472 Cvar_RegisterVariable(&r_batchmode);
3473 Cvar_RegisterVariable(&r_glsl_saturation);
3474 Cvar_RegisterVariable(&r_framedatasize);
3475 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3476 Cvar_SetValue("r_fullbrights", 0);
3477 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3479 Cvar_RegisterVariable(&r_track_sprites);
3480 Cvar_RegisterVariable(&r_track_sprites_flags);
3481 Cvar_RegisterVariable(&r_track_sprites_scalew);
3482 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3485 extern void R_Textures_Init(void);
3486 extern void GL_Draw_Init(void);
3487 extern void GL_Main_Init(void);
3488 extern void R_Shadow_Init(void);
3489 extern void R_Sky_Init(void);
3490 extern void GL_Surf_Init(void);
3491 extern void R_Particles_Init(void);
3492 extern void R_Explosion_Init(void);
3493 extern void gl_backend_init(void);
3494 extern void Sbar_Init(void);
3495 extern void R_LightningBeams_Init(void);
3496 extern void Mod_RenderInit(void);
3498 void Render_Init(void)
3510 R_LightningBeams_Init();
3519 extern char *ENGINE_EXTENSIONS;
3522 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3523 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3524 gl_version = (const char *)qglGetString(GL_VERSION);
3525 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3529 if (!gl_platformextensions)
3530 gl_platformextensions = "";
3532 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3533 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3534 Con_Printf("GL_VERSION: %s\n", gl_version);
3535 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3536 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3538 VID_CheckExtensions();
3540 // LordHavoc: report supported extensions
3541 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3543 // clear to black (loading plaque will be seen over this)
3545 qglClearColor(0,0,0,1);CHECKGLERROR
3546 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3549 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3553 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3555 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3558 p = r_refdef.view.frustum + i;
3563 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3567 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3571 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3575 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3579 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3583 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3587 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3591 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3599 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3603 for (i = 0;i < numplanes;i++)
3610 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3614 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3618 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3622 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3626 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3630 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3634 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3638 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3646 //==================================================================================
3648 // LordHavoc: this stores temporary data used within the same frame
3650 qboolean r_framedata_failed;
3651 static size_t r_framedata_size;
3652 static size_t r_framedata_current;
3653 static void *r_framedata_base;
3655 void R_FrameData_Reset(void)
3657 if (r_framedata_base);
3658 Mem_Free(r_framedata_base);
3659 r_framedata_base = NULL;
3660 r_framedata_size = 0;
3661 r_framedata_current = 0;
3662 r_framedata_failed = false;
3665 void R_FrameData_NewFrame(void)
3668 if (r_framedata_failed)
3669 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
3670 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
3671 wantedsize = bound(65536, wantedsize, 128*1024*1024);
3672 if (r_framedata_size != wantedsize)
3674 r_framedata_size = wantedsize;
3675 if (r_framedata_base);
3676 Mem_Free(r_framedata_base);
3677 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
3679 r_framedata_current = 0;
3680 r_framedata_failed = false;
3683 void *R_FrameData_Alloc(size_t size)
3687 // align to 16 byte boundary
3688 size = (size + 15) & ~15;
3689 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
3690 r_framedata_current += size;
3693 if (r_framedata_current > r_framedata_size)
3694 r_framedata_failed = true;
3696 // return NULL on everything after a failure
3697 if (r_framedata_failed)
3703 void *R_FrameData_Store(size_t size, void *data)
3705 void *d = R_FrameData_Alloc(size);
3707 memcpy(d, data, size);
3711 //==================================================================================
3713 // LordHavoc: animcache originally written by Echon, rewritten since then
3716 * Animation cache prevents re-generating mesh data for an animated model
3717 * multiple times in one frame for lighting, shadowing, reflections, etc.
3720 void R_AnimCache_Free(void)
3724 void R_AnimCache_ClearCache(void)
3727 entity_render_t *ent;
3729 for (i = 0;i < r_refdef.scene.numentities;i++)
3731 ent = r_refdef.scene.entities[i];
3732 ent->animcache_vertex3f = NULL;
3733 ent->animcache_normal3f = NULL;
3734 ent->animcache_svector3f = NULL;
3735 ent->animcache_tvector3f = NULL;
3739 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3741 dp_model_t *model = ent->model;
3743 // see if it's already cached this frame
3744 if (ent->animcache_vertex3f)
3746 // add normals/tangents if needed
3747 if (wantnormals || wanttangents)
3749 if (ent->animcache_normal3f)
3750 wantnormals = false;
3751 if (ent->animcache_svector3f)
3752 wanttangents = false;
3753 if (wantnormals || wanttangents)
3755 numvertices = model->surfmesh.num_vertices;
3757 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3760 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3761 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3763 if (!r_framedata_failed)
3764 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
3770 // see if this ent is worth caching
3771 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
3773 // get some memory for this entity and generate mesh data
3774 numvertices = model->surfmesh.num_vertices;
3775 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3777 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3780 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3781 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3783 if (!r_framedata_failed)
3784 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
3786 return !r_framedata_failed;
3789 void R_AnimCache_CacheVisibleEntities(void)
3792 qboolean wantnormals = !r_showsurfaces.integer;
3793 qboolean wanttangents = !r_showsurfaces.integer;
3795 switch(vid.renderpath)
3797 case RENDERPATH_GL20:
3799 case RENDERPATH_GL13:
3800 case RENDERPATH_GL11:
3801 wanttangents = false;
3805 // TODO: thread this
3806 // NOTE: R_PrepareRTLights() also caches entities
3808 for (i = 0;i < r_refdef.scene.numentities;i++)
3809 if (r_refdef.viewcache.entityvisible[i])
3810 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3812 if (r_shadows.integer)
3813 for (i = 0;i < r_refdef.scene.numentities;i++)
3814 if (!r_refdef.viewcache.entityvisible[i])
3815 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
3818 //==================================================================================
3820 static void R_View_UpdateEntityLighting (void)
3823 entity_render_t *ent;
3824 vec3_t tempdiffusenormal, avg;
3825 vec_t f, fa, fd, fdd;
3827 for (i = 0;i < r_refdef.scene.numentities;i++)
3829 ent = r_refdef.scene.entities[i];
3831 // skip unseen models
3832 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3836 if (ent->model && ent->model->brush.num_leafs)
3838 // TODO: use modellight for r_ambient settings on world?
3839 VectorSet(ent->modellight_ambient, 0, 0, 0);
3840 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3841 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3845 // fetch the lighting from the worldmodel data
3846 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));
3847 VectorClear(ent->modellight_diffuse);
3848 VectorClear(tempdiffusenormal);
3849 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3852 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3853 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3854 if(ent->flags & RENDER_EQUALIZE)
3856 // first fix up ambient lighting...
3857 if(r_equalize_entities_minambient.value > 0)
3859 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3862 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3863 if(fa < r_equalize_entities_minambient.value * fd)
3866 // fa'/fd' = minambient
3867 // fa'+0.25*fd' = fa+0.25*fd
3869 // fa' = fd' * minambient
3870 // fd'*(0.25+minambient) = fa+0.25*fd
3872 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3873 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3875 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3876 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
3877 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3878 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3883 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3885 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3886 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3889 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3890 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3891 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3897 VectorSet(ent->modellight_ambient, 1, 1, 1);
3899 // move the light direction into modelspace coordinates for lighting code
3900 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3901 if(VectorLength2(ent->modellight_lightdir) == 0)
3902 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3903 VectorNormalize(ent->modellight_lightdir);
3907 #define MAX_LINEOFSIGHTTRACES 64
3909 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3912 vec3_t boxmins, boxmaxs;
3915 dp_model_t *model = r_refdef.scene.worldmodel;
3917 if (!model || !model->brush.TraceLineOfSight)
3920 // expand the box a little
3921 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3922 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3923 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3924 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3925 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3926 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3929 VectorCopy(eye, start);
3930 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3931 if (model->brush.TraceLineOfSight(model, start, end))
3934 // try various random positions
3935 for (i = 0;i < numsamples;i++)
3937 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3938 if (model->brush.TraceLineOfSight(model, start, end))
3946 static void R_View_UpdateEntityVisible (void)
3951 entity_render_t *ent;
3953 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3954 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3956 // worldmodel can check visibility
3957 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3958 for (i = 0;i < r_refdef.scene.numentities;i++)
3960 ent = r_refdef.scene.entities[i];
3961 if (!(ent->flags & renderimask))
3962 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)))
3963 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))
3964 r_refdef.viewcache.entityvisible[i] = true;
3966 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3968 for (i = 0;i < r_refdef.scene.numentities;i++)
3970 ent = r_refdef.scene.entities[i];
3971 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3973 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3975 continue; // temp entities do pvs only
3976 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3977 ent->last_trace_visibility = realtime;
3978 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3979 r_refdef.viewcache.entityvisible[i] = 0;
3986 // no worldmodel or it can't check visibility
3987 for (i = 0;i < r_refdef.scene.numentities;i++)
3989 ent = r_refdef.scene.entities[i];
3990 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));
3995 /// only used if skyrendermasked, and normally returns false
3996 int R_DrawBrushModelsSky (void)
3999 entity_render_t *ent;
4002 for (i = 0;i < r_refdef.scene.numentities;i++)
4004 if (!r_refdef.viewcache.entityvisible[i])
4006 ent = r_refdef.scene.entities[i];
4007 if (!ent->model || !ent->model->DrawSky)
4009 ent->model->DrawSky(ent);
4015 static void R_DrawNoModel(entity_render_t *ent);
4016 static void R_DrawModels(void)
4019 entity_render_t *ent;
4021 for (i = 0;i < r_refdef.scene.numentities;i++)
4023 if (!r_refdef.viewcache.entityvisible[i])
4025 ent = r_refdef.scene.entities[i];
4026 r_refdef.stats.entities++;
4027 if (ent->model && ent->model->Draw != NULL)
4028 ent->model->Draw(ent);
4034 static void R_DrawModelsDepth(void)
4037 entity_render_t *ent;
4039 for (i = 0;i < r_refdef.scene.numentities;i++)
4041 if (!r_refdef.viewcache.entityvisible[i])
4043 ent = r_refdef.scene.entities[i];
4044 if (ent->model && ent->model->DrawDepth != NULL)
4045 ent->model->DrawDepth(ent);
4049 static void R_DrawModelsDebug(void)
4052 entity_render_t *ent;
4054 for (i = 0;i < r_refdef.scene.numentities;i++)
4056 if (!r_refdef.viewcache.entityvisible[i])
4058 ent = r_refdef.scene.entities[i];
4059 if (ent->model && ent->model->DrawDebug != NULL)
4060 ent->model->DrawDebug(ent);
4064 static void R_DrawModelsAddWaterPlanes(void)
4067 entity_render_t *ent;
4069 for (i = 0;i < r_refdef.scene.numentities;i++)
4071 if (!r_refdef.viewcache.entityvisible[i])
4073 ent = r_refdef.scene.entities[i];
4074 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4075 ent->model->DrawAddWaterPlanes(ent);
4079 static void R_View_SetFrustum(void)
4082 double slopex, slopey;
4083 vec3_t forward, left, up, origin;
4085 // we can't trust r_refdef.view.forward and friends in reflected scenes
4086 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4089 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4090 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4091 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4092 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4093 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4094 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4095 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4096 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4097 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4098 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4099 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4100 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4104 zNear = r_refdef.nearclip;
4105 nudge = 1.0 - 1.0 / (1<<23);
4106 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4107 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4108 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4109 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4110 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4111 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4112 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4113 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4119 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4120 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4121 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4122 r_refdef.view.frustum[0].dist = m[15] - m[12];
4124 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4125 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4126 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4127 r_refdef.view.frustum[1].dist = m[15] + m[12];
4129 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4130 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4131 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4132 r_refdef.view.frustum[2].dist = m[15] - m[13];
4134 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4135 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4136 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4137 r_refdef.view.frustum[3].dist = m[15] + m[13];
4139 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4140 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4141 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4142 r_refdef.view.frustum[4].dist = m[15] - m[14];
4144 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4145 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4146 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4147 r_refdef.view.frustum[5].dist = m[15] + m[14];
4150 if (r_refdef.view.useperspective)
4152 slopex = 1.0 / r_refdef.view.frustum_x;
4153 slopey = 1.0 / r_refdef.view.frustum_y;
4154 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
4155 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
4156 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
4157 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
4158 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4160 // Leaving those out was a mistake, those were in the old code, and they
4161 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4162 // I couldn't reproduce it after adding those normalizations. --blub
4163 VectorNormalize(r_refdef.view.frustum[0].normal);
4164 VectorNormalize(r_refdef.view.frustum[1].normal);
4165 VectorNormalize(r_refdef.view.frustum[2].normal);
4166 VectorNormalize(r_refdef.view.frustum[3].normal);
4168 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4169 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]);
4170 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]);
4171 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]);
4172 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]);
4174 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4175 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4176 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4177 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4178 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4182 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4183 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4184 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4185 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
4186 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4187 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
4188 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
4189 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
4190 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
4191 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4193 r_refdef.view.numfrustumplanes = 5;
4195 if (r_refdef.view.useclipplane)
4197 r_refdef.view.numfrustumplanes = 6;
4198 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4201 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4202 PlaneClassify(r_refdef.view.frustum + i);
4204 // LordHavoc: note to all quake engine coders, Quake had a special case
4205 // for 90 degrees which assumed a square view (wrong), so I removed it,
4206 // Quake2 has it disabled as well.
4208 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4209 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4210 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4211 //PlaneClassify(&frustum[0]);
4213 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4214 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4215 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4216 //PlaneClassify(&frustum[1]);
4218 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4219 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4220 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4221 //PlaneClassify(&frustum[2]);
4223 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4224 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4225 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4226 //PlaneClassify(&frustum[3]);
4229 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4230 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4231 //PlaneClassify(&frustum[4]);
4234 void R_View_Update(void)
4236 R_Main_ResizeViewCache();
4237 R_View_SetFrustum();
4238 R_View_WorldVisibility(r_refdef.view.useclipplane);
4239 R_View_UpdateEntityVisible();
4240 R_View_UpdateEntityLighting();
4243 void R_SetupView(qboolean allowwaterclippingplane)
4245 const double *customclipplane = NULL;
4247 if (r_refdef.view.useclipplane && allowwaterclippingplane)
4249 // LordHavoc: couldn't figure out how to make this approach the
4250 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4251 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4252 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4253 dist = r_refdef.view.clipplane.dist;
4254 plane[0] = r_refdef.view.clipplane.normal[0];
4255 plane[1] = r_refdef.view.clipplane.normal[1];
4256 plane[2] = r_refdef.view.clipplane.normal[2];
4258 customclipplane = plane;
4261 if (!r_refdef.view.useperspective)
4262 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);
4263 else if (vid.stencil && r_useinfinitefarclip.integer)
4264 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);
4266 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);
4267 R_SetViewport(&r_refdef.view.viewport);
4270 void R_ResetViewRendering2D(void)
4272 r_viewport_t viewport;
4275 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
4276 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);
4277 R_SetViewport(&viewport);
4278 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
4279 GL_Color(1, 1, 1, 1);
4280 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4281 GL_BlendFunc(GL_ONE, GL_ZERO);
4282 GL_AlphaTest(false);
4283 GL_ScissorTest(false);
4284 GL_DepthMask(false);
4285 GL_DepthRange(0, 1);
4286 GL_DepthTest(false);
4287 R_Mesh_Matrix(&identitymatrix);
4288 R_Mesh_ResetTextureState();
4289 GL_PolygonOffset(0, 0);
4290 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4291 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4292 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4293 qglStencilMask(~0);CHECKGLERROR
4294 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4295 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4296 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
4297 R_SetupGenericShader(true);
4300 void R_ResetViewRendering3D(void)
4305 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
4306 GL_Color(1, 1, 1, 1);
4307 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4308 GL_BlendFunc(GL_ONE, GL_ZERO);
4309 GL_AlphaTest(false);
4310 GL_ScissorTest(true);
4312 GL_DepthRange(0, 1);
4314 R_Mesh_Matrix(&identitymatrix);
4315 R_Mesh_ResetTextureState();
4316 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4317 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4318 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4319 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4320 qglStencilMask(~0);CHECKGLERROR
4321 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4322 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4323 GL_CullFace(r_refdef.view.cullface_back);
4324 R_SetupGenericShader(true);
4327 void R_RenderScene(void);
4328 void R_RenderWaterPlanes(void);
4330 static void R_Water_StartFrame(void)
4333 int waterwidth, waterheight, texturewidth, textureheight;
4334 r_waterstate_waterplane_t *p;
4336 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
4339 switch(vid.renderpath)
4341 case RENDERPATH_GL20:
4343 case RENDERPATH_GL13:
4344 case RENDERPATH_GL11:
4348 // set waterwidth and waterheight to the water resolution that will be
4349 // used (often less than the screen resolution for faster rendering)
4350 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
4351 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
4353 // calculate desired texture sizes
4354 // can't use water if the card does not support the texture size
4355 if (!r_water.integer || r_showsurfaces.integer)
4356 texturewidth = textureheight = waterwidth = waterheight = 0;
4357 else if (vid.support.arb_texture_non_power_of_two)
4359 texturewidth = waterwidth;
4360 textureheight = waterheight;
4364 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4365 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4368 // allocate textures as needed
4369 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4371 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4372 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4374 if (p->texture_refraction)
4375 R_FreeTexture(p->texture_refraction);
4376 p->texture_refraction = NULL;
4377 if (p->texture_reflection)
4378 R_FreeTexture(p->texture_reflection);
4379 p->texture_reflection = NULL;
4381 memset(&r_waterstate, 0, sizeof(r_waterstate));
4382 r_waterstate.texturewidth = texturewidth;
4383 r_waterstate.textureheight = textureheight;
4386 if (r_waterstate.texturewidth)
4388 r_waterstate.enabled = true;
4390 // when doing a reduced render (HDR) we want to use a smaller area
4391 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4392 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4394 // set up variables that will be used in shader setup
4395 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4396 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4397 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4398 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4401 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4402 r_waterstate.numwaterplanes = 0;
4405 void R_Water_AddWaterPlane(msurface_t *surface)
4407 int triangleindex, planeindex;
4413 r_waterstate_waterplane_t *p;
4414 texture_t *t = R_GetCurrentTexture(surface->texture);
4415 // just use the first triangle with a valid normal for any decisions
4416 VectorClear(normal);
4417 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4419 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4420 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4421 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4422 TriangleNormal(vert[0], vert[1], vert[2], normal);
4423 if (VectorLength2(normal) >= 0.001)
4427 VectorCopy(normal, plane.normal);
4428 VectorNormalize(plane.normal);
4429 plane.dist = DotProduct(vert[0], plane.normal);
4430 PlaneClassify(&plane);
4431 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4433 // skip backfaces (except if nocullface is set)
4434 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4436 VectorNegate(plane.normal, plane.normal);
4438 PlaneClassify(&plane);
4442 // find a matching plane if there is one
4443 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4444 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4446 if (planeindex >= r_waterstate.maxwaterplanes)
4447 return; // nothing we can do, out of planes
4449 // if this triangle does not fit any known plane rendered this frame, add one
4450 if (planeindex >= r_waterstate.numwaterplanes)
4452 // store the new plane
4453 r_waterstate.numwaterplanes++;
4455 // clear materialflags and pvs
4456 p->materialflags = 0;
4457 p->pvsvalid = false;
4459 // merge this surface's materialflags into the waterplane
4460 p->materialflags |= t->currentmaterialflags;
4461 // merge this surface's PVS into the waterplane
4462 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4463 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4464 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4466 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4471 static void R_Water_ProcessPlanes(void)
4473 r_refdef_view_t originalview;
4474 r_refdef_view_t myview;
4476 r_waterstate_waterplane_t *p;
4478 originalview = r_refdef.view;
4480 // make sure enough textures are allocated
4481 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4483 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4485 if (!p->texture_refraction)
4486 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);
4487 if (!p->texture_refraction)
4491 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4493 if (!p->texture_reflection)
4494 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);
4495 if (!p->texture_reflection)
4501 r_refdef.view = originalview;
4502 r_refdef.view.showdebug = false;
4503 r_refdef.view.width = r_waterstate.waterwidth;
4504 r_refdef.view.height = r_waterstate.waterheight;
4505 r_refdef.view.useclipplane = true;
4506 myview = r_refdef.view;
4507 r_waterstate.renderingscene = true;
4508 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4510 // render the normal view scene and copy into texture
4511 // (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)
4512 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4514 r_refdef.view = myview;
4515 r_refdef.view.clipplane = p->plane;
4516 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4517 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4518 PlaneClassify(&r_refdef.view.clipplane);
4520 R_ResetViewRendering3D();
4521 R_ClearScreen(r_refdef.fogenabled);
4525 // copy view into the screen texture
4526 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4527 GL_ActiveTexture(0);
4529 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
4532 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4534 r_refdef.view = myview;
4535 // render reflected scene and copy into texture
4536 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4537 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4538 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4539 r_refdef.view.clipplane = p->plane;
4540 // reverse the cullface settings for this render
4541 r_refdef.view.cullface_front = GL_FRONT;
4542 r_refdef.view.cullface_back = GL_BACK;
4543 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4545 r_refdef.view.usecustompvs = true;
4547 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4549 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4552 R_ResetViewRendering3D();
4553 R_ClearScreen(r_refdef.fogenabled);
4557 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4558 GL_ActiveTexture(0);
4560 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
4563 r_waterstate.renderingscene = false;
4564 r_refdef.view = originalview;
4565 R_ResetViewRendering3D();
4566 R_ClearScreen(r_refdef.fogenabled);
4570 r_refdef.view = originalview;
4571 r_waterstate.renderingscene = false;
4572 Cvar_SetValueQuick(&r_water, 0);
4573 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4577 void R_Bloom_StartFrame(void)
4579 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4581 switch(vid.renderpath)
4583 case RENDERPATH_GL20:
4585 case RENDERPATH_GL13:
4586 case RENDERPATH_GL11:
4590 // set bloomwidth and bloomheight to the bloom resolution that will be
4591 // used (often less than the screen resolution for faster rendering)
4592 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4593 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4594 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4595 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
4596 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
4598 // calculate desired texture sizes
4599 if (vid.support.arb_texture_non_power_of_two)
4601 screentexturewidth = r_refdef.view.width;
4602 screentextureheight = r_refdef.view.height;
4603 bloomtexturewidth = r_bloomstate.bloomwidth;
4604 bloomtextureheight = r_bloomstate.bloomheight;
4608 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4609 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4610 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4611 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4614 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))
4616 Cvar_SetValueQuick(&r_hdr, 0);
4617 Cvar_SetValueQuick(&r_bloom, 0);
4618 Cvar_SetValueQuick(&r_motionblur, 0);
4619 Cvar_SetValueQuick(&r_damageblur, 0);
4622 if (!(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)))
4623 screentexturewidth = screentextureheight = 0;
4624 if (!r_hdr.integer && !r_bloom.integer)
4625 bloomtexturewidth = bloomtextureheight = 0;
4627 // allocate textures as needed
4628 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4630 if (r_bloomstate.texture_screen)
4631 R_FreeTexture(r_bloomstate.texture_screen);
4632 r_bloomstate.texture_screen = NULL;
4633 r_bloomstate.screentexturewidth = screentexturewidth;
4634 r_bloomstate.screentextureheight = screentextureheight;
4635 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4636 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);
4638 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4640 if (r_bloomstate.texture_bloom)
4641 R_FreeTexture(r_bloomstate.texture_bloom);
4642 r_bloomstate.texture_bloom = NULL;
4643 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4644 r_bloomstate.bloomtextureheight = bloomtextureheight;
4645 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4646 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);
4649 // when doing a reduced render (HDR) we want to use a smaller area
4650 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4651 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4652 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4653 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4654 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4656 // set up a texcoord array for the full resolution screen image
4657 // (we have to keep this around to copy back during final render)
4658 r_bloomstate.screentexcoord2f[0] = 0;
4659 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4660 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4661 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4662 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4663 r_bloomstate.screentexcoord2f[5] = 0;
4664 r_bloomstate.screentexcoord2f[6] = 0;
4665 r_bloomstate.screentexcoord2f[7] = 0;
4667 // set up a texcoord array for the reduced resolution bloom image
4668 // (which will be additive blended over the screen image)
4669 r_bloomstate.bloomtexcoord2f[0] = 0;
4670 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4671 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4672 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4673 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4674 r_bloomstate.bloomtexcoord2f[5] = 0;
4675 r_bloomstate.bloomtexcoord2f[6] = 0;
4676 r_bloomstate.bloomtexcoord2f[7] = 0;
4678 if (r_hdr.integer || r_bloom.integer)
4680 r_bloomstate.enabled = true;
4681 r_bloomstate.hdr = r_hdr.integer != 0;
4684 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);
4687 void R_Bloom_CopyBloomTexture(float colorscale)
4689 r_refdef.stats.bloom++;
4691 // scale down screen texture to the bloom texture size
4693 R_SetViewport(&r_bloomstate.viewport);
4694 GL_BlendFunc(GL_ONE, GL_ZERO);
4695 GL_Color(colorscale, colorscale, colorscale, 1);
4696 // TODO: optimize with multitexture or GLSL
4697 R_SetupGenericShader(true);
4698 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4699 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4700 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4701 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4703 // we now have a bloom image in the framebuffer
4704 // copy it into the bloom image texture for later processing
4705 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4706 GL_ActiveTexture(0);
4708 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4709 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4712 void R_Bloom_CopyHDRTexture(void)
4714 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4715 GL_ActiveTexture(0);
4717 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
4718 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4721 void R_Bloom_MakeTexture(void)
4724 float xoffset, yoffset, r, brighten;
4726 r_refdef.stats.bloom++;
4728 R_ResetViewRendering2D();
4729 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4730 R_Mesh_ColorPointer(NULL, 0, 0);
4731 R_SetupGenericShader(true);
4733 // we have a bloom image in the framebuffer
4735 R_SetViewport(&r_bloomstate.viewport);
4737 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4740 r = bound(0, r_bloom_colorexponent.value / x, 1);
4741 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4742 GL_Color(r, r, r, 1);
4743 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4744 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4745 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4746 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4748 // copy the vertically blurred bloom view to a texture
4749 GL_ActiveTexture(0);
4751 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4752 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4755 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4756 brighten = r_bloom_brighten.value;
4758 brighten *= r_hdr_range.value;
4759 brighten = sqrt(brighten);
4761 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4762 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4763 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4765 for (dir = 0;dir < 2;dir++)
4767 // blend on at multiple vertical offsets to achieve a vertical blur
4768 // TODO: do offset blends using GLSL
4769 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4770 GL_BlendFunc(GL_ONE, GL_ZERO);
4771 for (x = -range;x <= range;x++)
4773 if (!dir){xoffset = 0;yoffset = x;}
4774 else {xoffset = x;yoffset = 0;}
4775 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4776 yoffset /= (float)r_bloomstate.bloomtextureheight;
4777 // compute a texcoord array with the specified x and y offset
4778 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4779 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4780 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4781 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4782 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4783 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4784 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4785 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4786 // this r value looks like a 'dot' particle, fading sharply to
4787 // black at the edges
4788 // (probably not realistic but looks good enough)
4789 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4790 //r = brighten/(range*2+1);
4791 r = brighten / (range * 2 + 1);
4793 r *= (1 - x*x/(float)(range*range));
4794 GL_Color(r, r, r, 1);
4795 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4796 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4797 GL_BlendFunc(GL_ONE, GL_ONE);
4800 // copy the vertically blurred bloom view to a texture
4801 GL_ActiveTexture(0);
4803 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4804 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4807 // apply subtract last
4808 // (just like it would be in a GLSL shader)
4809 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
4811 GL_BlendFunc(GL_ONE, GL_ZERO);
4812 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4813 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4814 GL_Color(1, 1, 1, 1);
4815 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4816 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4818 GL_BlendFunc(GL_ONE, GL_ONE);
4819 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4820 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4821 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4822 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4823 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4824 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4825 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4827 // copy the darkened bloom view to a texture
4828 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4829 GL_ActiveTexture(0);
4831 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4832 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4836 void R_HDR_RenderBloomTexture(void)
4838 int oldwidth, oldheight;
4839 float oldcolorscale;
4841 oldcolorscale = r_refdef.view.colorscale;
4842 oldwidth = r_refdef.view.width;
4843 oldheight = r_refdef.view.height;
4844 r_refdef.view.width = r_bloomstate.bloomwidth;
4845 r_refdef.view.height = r_bloomstate.bloomheight;
4847 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4848 // TODO: add exposure compensation features
4849 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4851 r_refdef.view.showdebug = false;
4852 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4854 R_ResetViewRendering3D();
4856 R_ClearScreen(r_refdef.fogenabled);
4857 if (r_timereport_active)
4858 R_TimeReport("HDRclear");
4861 if (r_timereport_active)
4862 R_TimeReport("visibility");
4864 // only do secondary renders with HDR if r_hdr is 2 or higher
4865 r_waterstate.numwaterplanes = 0;
4866 if (r_waterstate.enabled && r_hdr.integer >= 2)
4867 R_RenderWaterPlanes();
4869 r_refdef.view.showdebug = true;
4871 r_waterstate.numwaterplanes = 0;
4873 R_ResetViewRendering2D();
4875 R_Bloom_CopyHDRTexture();
4876 R_Bloom_MakeTexture();
4878 // restore the view settings
4879 r_refdef.view.width = oldwidth;
4880 r_refdef.view.height = oldheight;
4881 r_refdef.view.colorscale = oldcolorscale;
4883 R_ResetViewRendering3D();
4885 R_ClearScreen(r_refdef.fogenabled);
4886 if (r_timereport_active)
4887 R_TimeReport("viewclear");
4890 static void R_BlendView(void)
4892 unsigned int permutation;
4894 switch (vid.renderpath)
4896 case RENDERPATH_GL20:
4898 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4899 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4900 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4901 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4902 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4904 if (r_bloomstate.texture_screen)
4906 // make sure the buffer is available
4907 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4909 R_ResetViewRendering2D();
4910 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4911 R_Mesh_ColorPointer(NULL, 0, 0);
4912 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4913 GL_ActiveTexture(0);CHECKGLERROR
4915 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4917 // declare variables
4919 static float avgspeed;
4921 speed = VectorLength(cl.movement_velocity);
4923 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4924 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4926 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4927 speed = bound(0, speed, 1);
4928 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4930 // calculate values into a standard alpha
4931 cl.motionbluralpha = 1 - exp(-
4933 (r_motionblur.value * speed / 80)
4935 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4938 max(0.0001, cl.time - cl.oldtime) // fps independent
4941 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4942 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4944 if (cl.motionbluralpha > 0)
4946 R_SetupGenericShader(true);
4947 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4948 GL_Color(1, 1, 1, cl.motionbluralpha);
4949 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4950 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4951 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4952 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4956 // copy view into the screen texture
4957 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
4958 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4960 else if (!r_bloomstate.texture_bloom)
4961 break; // no screen processing, no bloom, skip it
4963 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4965 // render simple bloom effect
4966 // copy the screen and shrink it and darken it for the bloom process
4967 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4968 // make the bloom texture
4969 R_Bloom_MakeTexture();
4972 R_ResetViewRendering2D();
4973 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4974 R_Mesh_ColorPointer(NULL, 0, 0);
4975 GL_Color(1, 1, 1, 1);
4976 GL_BlendFunc(GL_ONE, GL_ZERO);
4977 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4978 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4979 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4980 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4981 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4982 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4983 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4984 if (r_glsl_permutation->loc_TintColor >= 0)
4985 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4986 if (r_glsl_permutation->loc_ClientTime >= 0)
4987 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4988 if (r_glsl_permutation->loc_PixelSize >= 0)
4989 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4990 if (r_glsl_permutation->loc_UserVec1 >= 0)
4992 float a=0, b=0, c=0, d=0;
4993 #if _MSC_VER >= 1400
4994 #define sscanf sscanf_s
4996 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4997 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4999 if (r_glsl_permutation->loc_UserVec2 >= 0)
5001 float a=0, b=0, c=0, d=0;
5002 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
5003 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
5005 if (r_glsl_permutation->loc_UserVec3 >= 0)
5007 float a=0, b=0, c=0, d=0;
5008 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
5009 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
5011 if (r_glsl_permutation->loc_UserVec4 >= 0)
5013 float a=0, b=0, c=0, d=0;
5014 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
5015 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
5017 if (r_glsl_permutation->loc_Saturation >= 0)
5018 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
5019 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5020 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5022 case RENDERPATH_GL13:
5023 case RENDERPATH_GL11:
5024 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
5026 // apply a color tint to the whole view
5027 R_ResetViewRendering2D();
5028 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5029 R_Mesh_ColorPointer(NULL, 0, 0);
5030 R_SetupGenericShader(false);
5031 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5032 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
5033 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5039 matrix4x4_t r_waterscrollmatrix;
5041 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
5043 if (r_refdef.fog_density)
5045 r_refdef.fogcolor[0] = r_refdef.fog_red;
5046 r_refdef.fogcolor[1] = r_refdef.fog_green;
5047 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5049 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5050 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5051 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5052 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5056 VectorCopy(r_refdef.fogcolor, fogvec);
5057 // color.rgb *= ContrastBoost * SceneBrightness;
5058 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5059 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5060 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5061 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5066 void R_UpdateVariables(void)
5070 r_refdef.scene.ambient = r_ambient.value;
5072 r_refdef.farclip = r_farclip_base.value;
5073 if (r_refdef.scene.worldmodel)
5074 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5075 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5077 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5078 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5079 r_refdef.polygonfactor = 0;
5080 r_refdef.polygonoffset = 0;
5081 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5082 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5084 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5085 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5086 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
5087 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5088 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5089 if (r_showsurfaces.integer)
5091 r_refdef.scene.rtworld = false;
5092 r_refdef.scene.rtworldshadows = false;
5093 r_refdef.scene.rtdlight = false;
5094 r_refdef.scene.rtdlightshadows = false;
5095 r_refdef.lightmapintensity = 0;
5098 if (gamemode == GAME_NEHAHRA)
5100 if (gl_fogenable.integer)
5102 r_refdef.oldgl_fogenable = true;
5103 r_refdef.fog_density = gl_fogdensity.value;
5104 r_refdef.fog_red = gl_fogred.value;
5105 r_refdef.fog_green = gl_foggreen.value;
5106 r_refdef.fog_blue = gl_fogblue.value;
5107 r_refdef.fog_alpha = 1;
5108 r_refdef.fog_start = 0;
5109 r_refdef.fog_end = gl_skyclip.value;
5110 r_refdef.fog_height = 1<<30;
5111 r_refdef.fog_fadedepth = 128;
5113 else if (r_refdef.oldgl_fogenable)
5115 r_refdef.oldgl_fogenable = false;
5116 r_refdef.fog_density = 0;
5117 r_refdef.fog_red = 0;
5118 r_refdef.fog_green = 0;
5119 r_refdef.fog_blue = 0;
5120 r_refdef.fog_alpha = 0;
5121 r_refdef.fog_start = 0;
5122 r_refdef.fog_end = 0;
5123 r_refdef.fog_height = 1<<30;
5124 r_refdef.fog_fadedepth = 128;
5128 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5129 r_refdef.fog_start = max(0, r_refdef.fog_start);
5130 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5132 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
5134 if (r_refdef.fog_density && r_drawfog.integer)
5136 r_refdef.fogenabled = true;
5137 // this is the point where the fog reaches 0.9986 alpha, which we
5138 // consider a good enough cutoff point for the texture
5139 // (0.9986 * 256 == 255.6)
5140 if (r_fog_exp2.integer)
5141 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5143 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5144 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5145 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5146 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5147 // fog color was already set
5148 // update the fog texture
5149 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)
5150 R_BuildFogTexture();
5153 r_refdef.fogenabled = false;
5155 switch(vid.renderpath)
5157 case RENDERPATH_GL20:
5158 if(v_glslgamma.integer && !vid_gammatables_trivial)
5160 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5162 // build GLSL gamma texture
5163 #define RAMPWIDTH 256
5164 unsigned short ramp[RAMPWIDTH * 3];
5165 unsigned char rampbgr[RAMPWIDTH][4];
5168 r_texture_gammaramps_serial = vid_gammatables_serial;
5170 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5171 for(i = 0; i < RAMPWIDTH; ++i)
5173 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5174 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5175 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5178 if (r_texture_gammaramps)
5180 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
5184 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);
5190 // remove GLSL gamma texture
5193 case RENDERPATH_GL13:
5194 case RENDERPATH_GL11:
5199 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5200 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5206 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5207 if( scenetype != r_currentscenetype ) {
5208 // store the old scenetype
5209 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5210 r_currentscenetype = scenetype;
5211 // move in the new scene
5212 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5221 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5223 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5224 if( scenetype == r_currentscenetype ) {
5225 return &r_refdef.scene;
5227 return &r_scenes_store[ scenetype ];
5236 void R_RenderView(void)
5238 if (r_timereport_active)
5239 R_TimeReport("start");
5240 r_frame++; // used only by R_GetCurrentTexture
5241 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5243 if (!r_drawentities.integer)
5244 r_refdef.scene.numentities = 0;
5246 R_AnimCache_ClearCache();
5247 R_FrameData_NewFrame();
5249 if (r_refdef.view.isoverlay)
5251 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5252 GL_Clear( GL_DEPTH_BUFFER_BIT );
5253 R_TimeReport("depthclear");
5255 r_refdef.view.showdebug = false;
5257 r_waterstate.enabled = false;
5258 r_waterstate.numwaterplanes = 0;
5266 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
5267 return; //Host_Error ("R_RenderView: NULL worldmodel");
5269 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
5271 // break apart the view matrix into vectors for various purposes
5272 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5273 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5274 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5275 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5276 // make an inverted copy of the view matrix for tracking sprites
5277 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5279 R_Shadow_UpdateWorldLightSelection();
5281 R_Bloom_StartFrame();
5282 R_Water_StartFrame();
5285 if (r_timereport_active)
5286 R_TimeReport("viewsetup");
5288 R_ResetViewRendering3D();
5290 if (r_refdef.view.clear || r_refdef.fogenabled)
5292 R_ClearScreen(r_refdef.fogenabled);
5293 if (r_timereport_active)
5294 R_TimeReport("viewclear");
5296 r_refdef.view.clear = true;
5298 // this produces a bloom texture to be used in R_BlendView() later
5299 if (r_hdr.integer && r_bloomstate.bloomwidth)
5300 R_HDR_RenderBloomTexture();
5302 r_refdef.view.showdebug = true;
5305 if (r_timereport_active)
5306 R_TimeReport("visibility");
5308 r_waterstate.numwaterplanes = 0;
5309 if (r_waterstate.enabled)
5310 R_RenderWaterPlanes();
5313 r_waterstate.numwaterplanes = 0;
5316 if (r_timereport_active)
5317 R_TimeReport("blendview");
5319 GL_Scissor(0, 0, vid.width, vid.height);
5320 GL_ScissorTest(false);
5324 void R_RenderWaterPlanes(void)
5326 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5328 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5329 if (r_timereport_active)
5330 R_TimeReport("waterworld");
5333 // don't let sound skip if going slow
5334 if (r_refdef.scene.extraupdate)
5337 R_DrawModelsAddWaterPlanes();
5338 if (r_timereport_active)
5339 R_TimeReport("watermodels");
5341 if (r_waterstate.numwaterplanes)
5343 R_Water_ProcessPlanes();
5344 if (r_timereport_active)
5345 R_TimeReport("waterscenes");
5349 extern void R_DrawLightningBeams (void);
5350 extern void VM_CL_AddPolygonsToMeshQueue (void);
5351 extern void R_DrawPortals (void);
5352 extern cvar_t cl_locs_show;
5353 static void R_DrawLocs(void);
5354 static void R_DrawEntityBBoxes(void);
5355 static void R_DrawModelDecals(void);
5356 extern cvar_t cl_decals_newsystem;
5357 extern qboolean r_shadow_usingdeferredprepass;
5358 void R_RenderScene(void)
5360 r_refdef.stats.renders++;
5364 // don't let sound skip if going slow
5365 if (r_refdef.scene.extraupdate)
5368 R_MeshQueue_BeginScene();
5372 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);
5374 if (cl.csqc_vidvars.drawworld)
5376 // don't let sound skip if going slow
5377 if (r_refdef.scene.extraupdate)
5380 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5382 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5383 if (r_timereport_active)
5384 R_TimeReport("worldsky");
5387 if (R_DrawBrushModelsSky() && r_timereport_active)
5388 R_TimeReport("bmodelsky");
5390 if (skyrendermasked && skyrenderlater)
5392 // we have to force off the water clipping plane while rendering sky
5396 if (r_timereport_active)
5397 R_TimeReport("sky");
5401 R_AnimCache_CacheVisibleEntities();
5402 if (r_timereport_active)
5403 R_TimeReport("animation");
5405 R_Shadow_PrepareLights();
5406 if (r_timereport_active)
5407 R_TimeReport("preparelights");
5409 if (r_shadow_usingdeferredprepass)
5410 R_Shadow_DrawPrepass();
5412 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5414 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5415 if (r_timereport_active)
5416 R_TimeReport("worlddepth");
5418 if (r_depthfirst.integer >= 2)
5420 R_DrawModelsDepth();
5421 if (r_timereport_active)
5422 R_TimeReport("modeldepth");
5425 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5427 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5428 if (r_timereport_active)
5429 R_TimeReport("world");
5432 // don't let sound skip if going slow
5433 if (r_refdef.scene.extraupdate)
5437 if (r_timereport_active)
5438 R_TimeReport("models");
5440 // don't let sound skip if going slow
5441 if (r_refdef.scene.extraupdate)
5444 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5446 R_DrawModelShadows();
5447 R_ResetViewRendering3D();
5448 // don't let sound skip if going slow
5449 if (r_refdef.scene.extraupdate)
5453 if (!r_shadow_usingdeferredprepass)
5455 R_Shadow_DrawLights();
5456 if (r_timereport_active)
5457 R_TimeReport("rtlights");
5460 // don't let sound skip if going slow
5461 if (r_refdef.scene.extraupdate)
5464 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5466 R_DrawModelShadows();
5467 R_ResetViewRendering3D();
5468 // don't let sound skip if going slow
5469 if (r_refdef.scene.extraupdate)
5473 if (cl.csqc_vidvars.drawworld)
5475 if (cl_decals_newsystem.integer)
5477 R_DrawModelDecals();
5478 if (r_timereport_active)
5479 R_TimeReport("modeldecals");
5484 if (r_timereport_active)
5485 R_TimeReport("decals");
5489 if (r_timereport_active)
5490 R_TimeReport("particles");
5493 if (r_timereport_active)
5494 R_TimeReport("explosions");
5496 R_DrawLightningBeams();
5497 if (r_timereport_active)
5498 R_TimeReport("lightning");
5501 R_SetupGenericShader(true);
5502 VM_CL_AddPolygonsToMeshQueue();
5504 if (r_refdef.view.showdebug)
5506 if (cl_locs_show.integer)
5509 if (r_timereport_active)
5510 R_TimeReport("showlocs");
5513 if (r_drawportals.integer)
5516 if (r_timereport_active)
5517 R_TimeReport("portals");
5520 if (r_showbboxes.value > 0)
5522 R_DrawEntityBBoxes();
5523 if (r_timereport_active)
5524 R_TimeReport("bboxes");
5528 R_SetupGenericShader(true);
5529 R_MeshQueue_RenderTransparent();
5530 if (r_timereport_active)
5531 R_TimeReport("drawtrans");
5533 R_SetupGenericShader(true);
5535 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))
5537 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5538 if (r_timereport_active)
5539 R_TimeReport("worlddebug");
5540 R_DrawModelsDebug();
5541 if (r_timereport_active)
5542 R_TimeReport("modeldebug");
5545 R_SetupGenericShader(true);
5547 if (cl.csqc_vidvars.drawworld)
5549 R_Shadow_DrawCoronas();
5550 if (r_timereport_active)
5551 R_TimeReport("coronas");
5554 // don't let sound skip if going slow
5555 if (r_refdef.scene.extraupdate)
5558 R_ResetViewRendering2D();
5561 static const unsigned short bboxelements[36] =
5571 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5574 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5576 RSurf_ActiveWorldEntity();
5578 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5579 GL_DepthMask(false);
5580 GL_DepthRange(0, 1);
5581 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5582 R_Mesh_ResetTextureState();
5584 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5585 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5586 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5587 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5588 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5589 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5590 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5591 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5592 R_FillColors(color4f, 8, cr, cg, cb, ca);
5593 if (r_refdef.fogenabled)
5595 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5597 f1 = RSurf_FogVertex(v);
5599 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5600 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5601 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5604 R_Mesh_VertexPointer(vertex3f, 0, 0);
5605 R_Mesh_ColorPointer(color4f, 0, 0);
5606 R_Mesh_ResetTextureState();
5607 R_SetupGenericShader(false);
5608 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5611 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5615 prvm_edict_t *edict;
5616 prvm_prog_t *prog_save = prog;
5618 // this function draws bounding boxes of server entities
5622 GL_CullFace(GL_NONE);
5623 R_SetupGenericShader(false);
5627 for (i = 0;i < numsurfaces;i++)
5629 edict = PRVM_EDICT_NUM(surfacelist[i]);
5630 switch ((int)edict->fields.server->solid)
5632 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5633 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5634 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5635 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5636 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5637 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5639 color[3] *= r_showbboxes.value;
5640 color[3] = bound(0, color[3], 1);
5641 GL_DepthTest(!r_showdisabledepthtest.integer);
5642 GL_CullFace(r_refdef.view.cullface_front);
5643 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5649 static void R_DrawEntityBBoxes(void)
5652 prvm_edict_t *edict;
5654 prvm_prog_t *prog_save = prog;
5656 // this function draws bounding boxes of server entities
5662 for (i = 0;i < prog->num_edicts;i++)
5664 edict = PRVM_EDICT_NUM(i);
5665 if (edict->priv.server->free)
5667 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5668 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5670 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5672 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5673 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5679 static const int nomodelelement3i[24] =
5691 static const unsigned short nomodelelement3s[24] =
5703 static const float nomodelvertex3f[6*3] =
5713 static const float nomodelcolor4f[6*4] =
5715 0.0f, 0.0f, 0.5f, 1.0f,
5716 0.0f, 0.0f, 0.5f, 1.0f,
5717 0.0f, 0.5f, 0.0f, 1.0f,
5718 0.0f, 0.5f, 0.0f, 1.0f,
5719 0.5f, 0.0f, 0.0f, 1.0f,
5720 0.5f, 0.0f, 0.0f, 1.0f
5723 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5729 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);
5731 // this is only called once per entity so numsurfaces is always 1, and
5732 // surfacelist is always {0}, so this code does not handle batches
5734 if (rsurface.ent_flags & RENDER_ADDITIVE)
5736 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5737 GL_DepthMask(false);
5739 else if (rsurface.ent_color[3] < 1)
5741 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5742 GL_DepthMask(false);
5746 GL_BlendFunc(GL_ONE, GL_ZERO);
5749 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5750 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5751 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5752 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5753 R_SetupGenericShader(false);
5754 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5755 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5756 R_Mesh_ColorPointer(color4f, 0, 0);
5757 for (i = 0, c = color4f;i < 6;i++, c += 4)
5759 c[0] *= rsurface.ent_color[0];
5760 c[1] *= rsurface.ent_color[1];
5761 c[2] *= rsurface.ent_color[2];
5762 c[3] *= rsurface.ent_color[3];
5764 if (r_refdef.fogenabled)
5766 for (i = 0, c = color4f;i < 6;i++, c += 4)
5768 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5770 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5771 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5772 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5775 R_Mesh_ResetTextureState();
5776 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5779 void R_DrawNoModel(entity_render_t *ent)
5782 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5783 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5784 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5786 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5789 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5791 vec3_t right1, right2, diff, normal;
5793 VectorSubtract (org2, org1, normal);
5795 // calculate 'right' vector for start
5796 VectorSubtract (r_refdef.view.origin, org1, diff);
5797 CrossProduct (normal, diff, right1);
5798 VectorNormalize (right1);
5800 // calculate 'right' vector for end
5801 VectorSubtract (r_refdef.view.origin, org2, diff);
5802 CrossProduct (normal, diff, right2);
5803 VectorNormalize (right2);
5805 vert[ 0] = org1[0] + width * right1[0];
5806 vert[ 1] = org1[1] + width * right1[1];
5807 vert[ 2] = org1[2] + width * right1[2];
5808 vert[ 3] = org1[0] - width * right1[0];
5809 vert[ 4] = org1[1] - width * right1[1];
5810 vert[ 5] = org1[2] - width * right1[2];
5811 vert[ 6] = org2[0] - width * right2[0];
5812 vert[ 7] = org2[1] - width * right2[1];
5813 vert[ 8] = org2[2] - width * right2[2];
5814 vert[ 9] = org2[0] + width * right2[0];
5815 vert[10] = org2[1] + width * right2[1];
5816 vert[11] = org2[2] + width * right2[2];
5819 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)
5821 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5822 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5823 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5824 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5825 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5826 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5827 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5828 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5829 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5830 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5831 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5832 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5835 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5840 VectorSet(v, x, y, z);
5841 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5842 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5844 if (i == mesh->numvertices)
5846 if (mesh->numvertices < mesh->maxvertices)
5848 VectorCopy(v, vertex3f);
5849 mesh->numvertices++;
5851 return mesh->numvertices;
5857 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5861 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5862 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5863 e = mesh->element3i + mesh->numtriangles * 3;
5864 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5866 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5867 if (mesh->numtriangles < mesh->maxtriangles)
5872 mesh->numtriangles++;
5874 element[1] = element[2];
5878 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5882 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5883 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5884 e = mesh->element3i + mesh->numtriangles * 3;
5885 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5887 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5888 if (mesh->numtriangles < mesh->maxtriangles)
5893 mesh->numtriangles++;
5895 element[1] = element[2];
5899 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5900 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5902 int planenum, planenum2;
5905 mplane_t *plane, *plane2;
5907 double temppoints[2][256*3];
5908 // figure out how large a bounding box we need to properly compute this brush
5910 for (w = 0;w < numplanes;w++)
5911 maxdist = max(maxdist, fabs(planes[w].dist));
5912 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5913 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5914 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5918 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5919 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5921 if (planenum2 == planenum)
5923 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);
5926 if (tempnumpoints < 3)
5928 // generate elements forming a triangle fan for this polygon
5929 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5933 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)
5935 texturelayer_t *layer;
5936 layer = t->currentlayers + t->currentnumlayers++;
5938 layer->depthmask = depthmask;
5939 layer->blendfunc1 = blendfunc1;
5940 layer->blendfunc2 = blendfunc2;
5941 layer->texture = texture;
5942 layer->texmatrix = *matrix;
5943 layer->color[0] = r * r_refdef.view.colorscale;
5944 layer->color[1] = g * r_refdef.view.colorscale;
5945 layer->color[2] = b * r_refdef.view.colorscale;
5946 layer->color[3] = a;
5949 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5952 index = parms[2] + r_refdef.scene.time * parms[3];
5953 index -= floor(index);
5957 case Q3WAVEFUNC_NONE:
5958 case Q3WAVEFUNC_NOISE:
5959 case Q3WAVEFUNC_COUNT:
5962 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5963 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5964 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5965 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5966 case Q3WAVEFUNC_TRIANGLE:
5968 f = index - floor(index);
5979 return (float)(parms[0] + parms[1] * f);
5982 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5987 matrix4x4_t matrix, temp;
5988 switch(tcmod->tcmod)
5992 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5993 matrix = r_waterscrollmatrix;
5995 matrix = identitymatrix;
5997 case Q3TCMOD_ENTITYTRANSLATE:
5998 // this is used in Q3 to allow the gamecode to control texcoord
5999 // scrolling on the entity, which is not supported in darkplaces yet.
6000 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
6002 case Q3TCMOD_ROTATE:
6003 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
6004 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
6005 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
6008 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
6010 case Q3TCMOD_SCROLL:
6011 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
6013 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
6014 w = (int) tcmod->parms[0];
6015 h = (int) tcmod->parms[1];
6016 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
6018 idx = (int) floor(f * w * h);
6019 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
6021 case Q3TCMOD_STRETCH:
6022 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
6023 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
6025 case Q3TCMOD_TRANSFORM:
6026 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
6027 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
6028 VectorSet(tcmat + 6, 0 , 0 , 1);
6029 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
6030 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
6032 case Q3TCMOD_TURBULENT:
6033 // this is handled in the RSurf_PrepareVertices function
6034 matrix = identitymatrix;
6038 Matrix4x4_Concat(texmatrix, &matrix, &temp);
6041 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
6043 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
6044 char name[MAX_QPATH];
6045 skinframe_t *skinframe;
6046 unsigned char pixels[296*194];
6047 strlcpy(cache->name, skinname, sizeof(cache->name));
6048 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6049 if (developer_loading.integer)
6050 Con_Printf("loading %s\n", name);
6051 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6052 if (!skinframe || !skinframe->base)
6055 fs_offset_t filesize;
6057 f = FS_LoadFile(name, tempmempool, true, &filesize);
6060 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
6061 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6065 cache->skinframe = skinframe;
6068 texture_t *R_GetCurrentTexture(texture_t *t)
6071 const entity_render_t *ent = rsurface.entity;
6072 dp_model_t *model = ent->model;
6073 q3shaderinfo_layer_tcmod_t *tcmod;
6075 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
6076 return t->currentframe;
6077 t->update_lastrenderframe = r_frame;
6078 t->update_lastrenderentity = (void *)ent;
6080 // switch to an alternate material if this is a q1bsp animated material
6082 texture_t *texture = t;
6083 int s = rsurface.ent_skinnum;
6084 if ((unsigned int)s >= (unsigned int)model->numskins)
6086 if (model->skinscenes)
6088 if (model->skinscenes[s].framecount > 1)
6089 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6091 s = model->skinscenes[s].firstframe;
6094 t = t + s * model->num_surfaces;
6097 // use an alternate animation if the entity's frame is not 0,
6098 // and only if the texture has an alternate animation
6099 if (rsurface.ent_alttextures && t->anim_total[1])
6100 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
6102 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
6104 texture->currentframe = t;
6107 // update currentskinframe to be a qw skin or animation frame
6108 if (rsurface.ent_qwskin >= 0)
6110 i = rsurface.ent_qwskin;
6111 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6113 r_qwskincache_size = cl.maxclients;
6115 Mem_Free(r_qwskincache);
6116 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6118 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6119 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6120 t->currentskinframe = r_qwskincache[i].skinframe;
6121 if (t->currentskinframe == NULL)
6122 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6124 else if (t->numskinframes >= 2)
6125 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6126 if (t->backgroundnumskinframes >= 2)
6127 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
6129 t->currentmaterialflags = t->basematerialflags;
6130 t->currentalpha = rsurface.ent_color[3];
6131 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
6132 t->currentalpha *= r_wateralpha.value;
6133 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
6134 t->currentalpha *= t->r_water_wateralpha;
6135 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
6136 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
6137 if (!(rsurface.ent_flags & RENDER_LIGHT))
6138 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
6139 else if (rsurface.modeltexcoordlightmap2f == NULL)
6141 // pick a model lighting mode
6142 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
6143 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
6145 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6147 if (rsurface.ent_flags & RENDER_ADDITIVE)
6148 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6149 else if (t->currentalpha < 1)
6150 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6151 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6152 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6153 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6154 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6155 if (t->backgroundnumskinframes)
6156 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6157 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6159 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
6160 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6163 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
6165 // there is no tcmod
6166 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6168 t->currenttexmatrix = r_waterscrollmatrix;
6169 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6171 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6173 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6174 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6177 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6178 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6179 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6180 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6182 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
6183 if (t->currentskinframe->qpixels)
6184 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6185 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6186 t->glosstexture = r_texture_black;
6187 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
6188 t->backgroundglosstexture = r_texture_black;
6189 t->specularpower = r_shadow_glossexponent.value;
6190 // TODO: store reference values for these in the texture?
6191 t->specularscale = 0;
6192 if (r_shadow_gloss.integer > 0)
6194 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6196 if (r_shadow_glossintensity.value > 0)
6198 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6199 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6200 t->specularscale = r_shadow_glossintensity.value;
6203 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6205 t->glosstexture = r_texture_white;
6206 t->backgroundglosstexture = r_texture_white;
6207 t->specularscale = r_shadow_gloss2intensity.value;
6208 t->specularpower = r_shadow_gloss2exponent.value;
6211 t->specularscale *= t->specularscalemod;
6212 t->specularpower *= t->specularpowermod;
6214 // lightmaps mode looks bad with dlights using actual texturing, so turn
6215 // off the colormap and glossmap, but leave the normalmap on as it still
6216 // accurately represents the shading involved
6217 if (gl_lightmaps.integer)
6219 t->basetexture = r_texture_grey128;
6220 t->backgroundbasetexture = NULL;
6221 t->specularscale = 0;
6222 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6225 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
6226 VectorClear(t->dlightcolor);
6227 t->currentnumlayers = 0;
6228 if (t->currentmaterialflags & MATERIALFLAG_WALL)
6231 int blendfunc1, blendfunc2;
6233 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6235 blendfunc1 = GL_SRC_ALPHA;
6236 blendfunc2 = GL_ONE;
6238 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6240 blendfunc1 = GL_SRC_ALPHA;
6241 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6243 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6245 blendfunc1 = t->customblendfunc[0];
6246 blendfunc2 = t->customblendfunc[1];
6250 blendfunc1 = GL_ONE;
6251 blendfunc2 = GL_ZERO;
6253 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
6254 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
6255 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
6256 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6258 // fullbright is not affected by r_refdef.lightmapintensity
6259 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]);
6260 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6261 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]);
6262 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6263 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]);
6267 vec3_t ambientcolor;
6269 // set the color tint used for lights affecting this surface
6270 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
6272 // q3bsp has no lightmap updates, so the lightstylevalue that
6273 // would normally be baked into the lightmap must be
6274 // applied to the color
6275 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
6276 if (model->type == mod_brushq3)
6277 colorscale *= r_refdef.scene.rtlightstylevalue[0];
6278 colorscale *= r_refdef.lightmapintensity;
6279 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
6280 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
6281 // basic lit geometry
6282 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]);
6283 // add pants/shirt if needed
6284 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6285 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]);
6286 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6287 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]);
6288 // now add ambient passes if needed
6289 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
6291 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]);
6292 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6293 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]);
6294 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6295 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]);
6298 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
6299 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]);
6300 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
6302 // if this is opaque use alpha blend which will darken the earlier
6305 // if this is an alpha blended material, all the earlier passes
6306 // were darkened by fog already, so we only need to add the fog
6307 // color ontop through the fog mask texture
6309 // if this is an additive blended material, all the earlier passes
6310 // were darkened by fog already, and we should not add fog color
6311 // (because the background was not darkened, there is no fog color
6312 // that was lost behind it).
6313 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]);
6317 return t->currentframe;
6320 rsurfacestate_t rsurface;
6322 void R_Mesh_ResizeArrays(int newvertices)
6325 if (rsurface.array_size >= newvertices)
6327 if (rsurface.array_modelvertex3f)
6328 Mem_Free(rsurface.array_modelvertex3f);
6329 rsurface.array_size = (newvertices + 1023) & ~1023;
6330 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
6331 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
6332 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
6333 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
6334 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
6335 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
6336 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
6337 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
6338 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
6339 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
6340 rsurface.array_color4f = base + rsurface.array_size * 27;
6341 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6344 void RSurf_ActiveWorldEntity(void)
6346 dp_model_t *model = r_refdef.scene.worldmodel;
6347 //if (rsurface.entity == r_refdef.scene.worldentity)
6349 rsurface.entity = r_refdef.scene.worldentity;
6350 rsurface.skeleton = NULL;
6351 rsurface.ent_skinnum = 0;
6352 rsurface.ent_qwskin = -1;
6353 rsurface.ent_shadertime = 0;
6354 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
6355 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6356 if (rsurface.array_size < model->surfmesh.num_vertices)
6357 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6358 rsurface.matrix = identitymatrix;
6359 rsurface.inversematrix = identitymatrix;
6360 rsurface.matrixscale = 1;
6361 rsurface.inversematrixscale = 1;
6362 R_Mesh_Matrix(&identitymatrix);
6363 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6364 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6365 rsurface.fograngerecip = r_refdef.fograngerecip;
6366 rsurface.fogheightfade = r_refdef.fogheightfade;
6367 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6368 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6369 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6370 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6371 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6372 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6373 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6374 VectorSet(rsurface.glowmod, 1, 1, 1);
6375 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6376 rsurface.frameblend[0].lerp = 1;
6377 rsurface.ent_alttextures = false;
6378 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6379 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6380 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6381 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6382 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6383 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6384 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6385 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6386 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6387 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6388 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6389 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6390 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6391 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6392 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6393 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6394 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6395 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6396 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6397 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6398 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6399 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6400 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6401 rsurface.modelelement3i = model->surfmesh.data_element3i;
6402 rsurface.modelelement3s = model->surfmesh.data_element3s;
6403 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6404 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6405 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6406 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6407 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6408 rsurface.modelsurfaces = model->data_surfaces;
6409 rsurface.generatedvertex = false;
6410 rsurface.vertex3f = rsurface.modelvertex3f;
6411 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6412 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6413 rsurface.svector3f = rsurface.modelsvector3f;
6414 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6415 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6416 rsurface.tvector3f = rsurface.modeltvector3f;
6417 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6418 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6419 rsurface.normal3f = rsurface.modelnormal3f;
6420 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6421 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6422 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6425 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6427 dp_model_t *model = ent->model;
6428 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6430 rsurface.entity = (entity_render_t *)ent;
6431 rsurface.skeleton = ent->skeleton;
6432 rsurface.ent_skinnum = ent->skinnum;
6433 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;
6434 rsurface.ent_shadertime = ent->shadertime;
6435 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6436 rsurface.ent_flags = ent->flags;
6437 if (rsurface.array_size < model->surfmesh.num_vertices)
6438 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6439 rsurface.matrix = ent->matrix;
6440 rsurface.inversematrix = ent->inversematrix;
6441 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6442 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6443 R_Mesh_Matrix(&rsurface.matrix);
6444 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6445 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6446 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6447 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6448 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6449 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6450 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6451 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6452 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6453 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6454 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6455 VectorCopy(ent->glowmod, rsurface.glowmod);
6456 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6457 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6458 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6459 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6460 if (ent->model->brush.submodel)
6462 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6463 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6465 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6467 if (ent->animcache_vertex3f && !r_framedata_failed)
6469 rsurface.modelvertex3f = ent->animcache_vertex3f;
6470 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
6471 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
6472 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
6474 else if (wanttangents)
6476 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6477 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6478 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6479 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6480 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6482 else if (wantnormals)
6484 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6485 rsurface.modelsvector3f = NULL;
6486 rsurface.modeltvector3f = NULL;
6487 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6488 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6492 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6493 rsurface.modelsvector3f = NULL;
6494 rsurface.modeltvector3f = NULL;
6495 rsurface.modelnormal3f = NULL;
6496 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6498 rsurface.modelvertex3f_bufferobject = 0;
6499 rsurface.modelvertex3f_bufferoffset = 0;
6500 rsurface.modelsvector3f_bufferobject = 0;
6501 rsurface.modelsvector3f_bufferoffset = 0;
6502 rsurface.modeltvector3f_bufferobject = 0;
6503 rsurface.modeltvector3f_bufferoffset = 0;
6504 rsurface.modelnormal3f_bufferobject = 0;
6505 rsurface.modelnormal3f_bufferoffset = 0;
6506 rsurface.generatedvertex = true;
6510 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6511 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6512 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6513 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6514 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6515 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6516 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6517 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6518 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6519 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6520 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6521 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6522 rsurface.generatedvertex = false;
6524 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6525 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6526 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6527 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6528 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6529 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6530 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6531 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6532 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6533 rsurface.modelelement3i = model->surfmesh.data_element3i;
6534 rsurface.modelelement3s = model->surfmesh.data_element3s;
6535 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6536 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6537 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6538 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6539 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6540 rsurface.modelsurfaces = model->data_surfaces;
6541 rsurface.vertex3f = rsurface.modelvertex3f;
6542 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6543 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6544 rsurface.svector3f = rsurface.modelsvector3f;
6545 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6546 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6547 rsurface.tvector3f = rsurface.modeltvector3f;
6548 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6549 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6550 rsurface.normal3f = rsurface.modelnormal3f;
6551 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6552 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6553 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6556 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)
6558 rsurface.entity = r_refdef.scene.worldentity;
6559 rsurface.skeleton = NULL;
6560 rsurface.ent_skinnum = 0;
6561 rsurface.ent_qwskin = -1;
6562 rsurface.ent_shadertime = shadertime;
6563 Vector4Set(rsurface.ent_color, r, g, b, a);
6564 rsurface.ent_flags = entflags;
6565 rsurface.modelnum_vertices = numvertices;
6566 rsurface.modelnum_triangles = numtriangles;
6567 if (rsurface.array_size < rsurface.modelnum_vertices)
6568 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6569 rsurface.matrix = *matrix;
6570 rsurface.inversematrix = *inversematrix;
6571 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6572 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6573 R_Mesh_Matrix(&rsurface.matrix);
6574 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6575 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6576 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6577 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6578 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6579 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6580 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6581 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6582 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6583 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6584 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6585 VectorSet(rsurface.glowmod, 1, 1, 1);
6586 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6587 rsurface.frameblend[0].lerp = 1;
6588 rsurface.ent_alttextures = false;
6589 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6590 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6593 rsurface.modelvertex3f = vertex3f;
6594 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6595 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6596 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6598 else if (wantnormals)
6600 rsurface.modelvertex3f = vertex3f;
6601 rsurface.modelsvector3f = NULL;
6602 rsurface.modeltvector3f = NULL;
6603 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6607 rsurface.modelvertex3f = vertex3f;
6608 rsurface.modelsvector3f = NULL;
6609 rsurface.modeltvector3f = NULL;
6610 rsurface.modelnormal3f = NULL;
6612 rsurface.modelvertex3f_bufferobject = 0;
6613 rsurface.modelvertex3f_bufferoffset = 0;
6614 rsurface.modelsvector3f_bufferobject = 0;
6615 rsurface.modelsvector3f_bufferoffset = 0;
6616 rsurface.modeltvector3f_bufferobject = 0;
6617 rsurface.modeltvector3f_bufferoffset = 0;
6618 rsurface.modelnormal3f_bufferobject = 0;
6619 rsurface.modelnormal3f_bufferoffset = 0;
6620 rsurface.generatedvertex = true;
6621 rsurface.modellightmapcolor4f = color4f;
6622 rsurface.modellightmapcolor4f_bufferobject = 0;
6623 rsurface.modellightmapcolor4f_bufferoffset = 0;
6624 rsurface.modeltexcoordtexture2f = texcoord2f;
6625 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6626 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6627 rsurface.modeltexcoordlightmap2f = NULL;
6628 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6629 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6630 rsurface.modelelement3i = element3i;
6631 rsurface.modelelement3s = element3s;
6632 rsurface.modelelement3i_bufferobject = 0;
6633 rsurface.modelelement3s_bufferobject = 0;
6634 rsurface.modellightmapoffsets = NULL;
6635 rsurface.modelsurfaces = NULL;
6636 rsurface.vertex3f = rsurface.modelvertex3f;
6637 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6638 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6639 rsurface.svector3f = rsurface.modelsvector3f;
6640 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6641 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6642 rsurface.tvector3f = rsurface.modeltvector3f;
6643 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6644 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6645 rsurface.normal3f = rsurface.modelnormal3f;
6646 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6647 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6648 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6650 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6652 if ((wantnormals || wanttangents) && !normal3f)
6653 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6654 if (wanttangents && !svector3f)
6655 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);
6659 float RSurf_FogPoint(const float *v)
6661 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6662 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6663 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6664 float FogHeightFade = r_refdef.fogheightfade;
6666 unsigned int fogmasktableindex;
6667 if (r_refdef.fogplaneviewabove)
6668 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6670 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6671 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6672 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6675 float RSurf_FogVertex(const float *v)
6677 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6678 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6679 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6680 float FogHeightFade = rsurface.fogheightfade;
6682 unsigned int fogmasktableindex;
6683 if (r_refdef.fogplaneviewabove)
6684 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6686 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6687 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6688 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6691 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6692 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6695 int texturesurfaceindex;
6700 const float *v1, *in_tc;
6702 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6704 q3shaderinfo_deform_t *deform;
6705 // 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
6706 if (rsurface.generatedvertex)
6708 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6709 generatenormals = true;
6710 for (i = 0;i < Q3MAXDEFORMS;i++)
6712 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6714 generatetangents = true;
6715 generatenormals = true;
6717 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6718 generatenormals = true;
6720 if (generatenormals && !rsurface.modelnormal3f)
6722 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6723 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6724 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6725 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6727 if (generatetangents && !rsurface.modelsvector3f)
6729 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6730 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6731 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6732 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6733 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6734 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6735 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);
6738 rsurface.vertex3f = rsurface.modelvertex3f;
6739 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6740 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6741 rsurface.svector3f = rsurface.modelsvector3f;
6742 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6743 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6744 rsurface.tvector3f = rsurface.modeltvector3f;
6745 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6746 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6747 rsurface.normal3f = rsurface.modelnormal3f;
6748 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6749 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6750 // if vertices are deformed (sprite flares and things in maps, possibly
6751 // water waves, bulges and other deformations), generate them into
6752 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6753 // (may be static model data or generated data for an animated model, or
6754 // the previous deform pass)
6755 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6757 switch (deform->deform)
6760 case Q3DEFORM_PROJECTIONSHADOW:
6761 case Q3DEFORM_TEXT0:
6762 case Q3DEFORM_TEXT1:
6763 case Q3DEFORM_TEXT2:
6764 case Q3DEFORM_TEXT3:
6765 case Q3DEFORM_TEXT4:
6766 case Q3DEFORM_TEXT5:
6767 case Q3DEFORM_TEXT6:
6768 case Q3DEFORM_TEXT7:
6771 case Q3DEFORM_AUTOSPRITE:
6772 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6773 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6774 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6775 VectorNormalize(newforward);
6776 VectorNormalize(newright);
6777 VectorNormalize(newup);
6778 // make deformed versions of only the model vertices used by the specified surfaces
6779 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6781 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6782 // a single autosprite surface can contain multiple sprites...
6783 for (j = 0;j < surface->num_vertices - 3;j += 4)
6785 VectorClear(center);
6786 for (i = 0;i < 4;i++)
6787 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6788 VectorScale(center, 0.25f, center);
6789 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6790 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6791 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6792 for (i = 0;i < 4;i++)
6794 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6795 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6798 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);
6799 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);
6801 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6802 rsurface.vertex3f_bufferobject = 0;
6803 rsurface.vertex3f_bufferoffset = 0;
6804 rsurface.svector3f = rsurface.array_deformedsvector3f;
6805 rsurface.svector3f_bufferobject = 0;
6806 rsurface.svector3f_bufferoffset = 0;
6807 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6808 rsurface.tvector3f_bufferobject = 0;
6809 rsurface.tvector3f_bufferoffset = 0;
6810 rsurface.normal3f = rsurface.array_deformednormal3f;
6811 rsurface.normal3f_bufferobject = 0;
6812 rsurface.normal3f_bufferoffset = 0;
6814 case Q3DEFORM_AUTOSPRITE2:
6815 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6816 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6817 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6818 VectorNormalize(newforward);
6819 VectorNormalize(newright);
6820 VectorNormalize(newup);
6821 // make deformed versions of only the model vertices used by the specified surfaces
6822 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6824 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6825 const float *v1, *v2;
6835 memset(shortest, 0, sizeof(shortest));
6836 // a single autosprite surface can contain multiple sprites...
6837 for (j = 0;j < surface->num_vertices - 3;j += 4)
6839 VectorClear(center);
6840 for (i = 0;i < 4;i++)
6841 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6842 VectorScale(center, 0.25f, center);
6843 // find the two shortest edges, then use them to define the
6844 // axis vectors for rotating around the central axis
6845 for (i = 0;i < 6;i++)
6847 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6848 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6850 Debug_PolygonBegin(NULL, 0);
6851 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6852 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);
6853 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6856 l = VectorDistance2(v1, v2);
6857 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6859 l += (1.0f / 1024.0f);
6860 if (shortest[0].length2 > l || i == 0)
6862 shortest[1] = shortest[0];
6863 shortest[0].length2 = l;
6864 shortest[0].v1 = v1;
6865 shortest[0].v2 = v2;
6867 else if (shortest[1].length2 > l || i == 1)
6869 shortest[1].length2 = l;
6870 shortest[1].v1 = v1;
6871 shortest[1].v2 = v2;
6874 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6875 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6877 Debug_PolygonBegin(NULL, 0);
6878 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6879 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);
6880 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6883 // this calculates the right vector from the shortest edge
6884 // and the up vector from the edge midpoints
6885 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6886 VectorNormalize(right);
6887 VectorSubtract(end, start, up);
6888 VectorNormalize(up);
6889 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6890 VectorSubtract(rsurface.localvieworigin, center, forward);
6891 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6892 VectorNegate(forward, forward);
6893 VectorReflect(forward, 0, up, forward);
6894 VectorNormalize(forward);
6895 CrossProduct(up, forward, newright);
6896 VectorNormalize(newright);
6898 Debug_PolygonBegin(NULL, 0);
6899 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);
6900 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6901 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6905 Debug_PolygonBegin(NULL, 0);
6906 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6907 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6908 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6911 // rotate the quad around the up axis vector, this is made
6912 // especially easy by the fact we know the quad is flat,
6913 // so we only have to subtract the center position and
6914 // measure distance along the right vector, and then
6915 // multiply that by the newright vector and add back the
6917 // we also need to subtract the old position to undo the
6918 // displacement from the center, which we do with a
6919 // DotProduct, the subtraction/addition of center is also
6920 // optimized into DotProducts here
6921 l = DotProduct(right, center);
6922 for (i = 0;i < 4;i++)
6924 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6925 f = DotProduct(right, v1) - l;
6926 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6929 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);
6930 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);
6932 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6933 rsurface.vertex3f_bufferobject = 0;
6934 rsurface.vertex3f_bufferoffset = 0;
6935 rsurface.svector3f = rsurface.array_deformedsvector3f;
6936 rsurface.svector3f_bufferobject = 0;
6937 rsurface.svector3f_bufferoffset = 0;
6938 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6939 rsurface.tvector3f_bufferobject = 0;
6940 rsurface.tvector3f_bufferoffset = 0;
6941 rsurface.normal3f = rsurface.array_deformednormal3f;
6942 rsurface.normal3f_bufferobject = 0;
6943 rsurface.normal3f_bufferoffset = 0;
6945 case Q3DEFORM_NORMAL:
6946 // deform the normals to make reflections wavey
6947 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6949 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6950 for (j = 0;j < surface->num_vertices;j++)
6953 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6954 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6955 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6956 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6957 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6958 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6959 VectorNormalize(normal);
6961 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);
6963 rsurface.svector3f = rsurface.array_deformedsvector3f;
6964 rsurface.svector3f_bufferobject = 0;
6965 rsurface.svector3f_bufferoffset = 0;
6966 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6967 rsurface.tvector3f_bufferobject = 0;
6968 rsurface.tvector3f_bufferoffset = 0;
6969 rsurface.normal3f = rsurface.array_deformednormal3f;
6970 rsurface.normal3f_bufferobject = 0;
6971 rsurface.normal3f_bufferoffset = 0;
6974 // deform vertex array to make wavey water and flags and such
6975 waveparms[0] = deform->waveparms[0];
6976 waveparms[1] = deform->waveparms[1];
6977 waveparms[2] = deform->waveparms[2];
6978 waveparms[3] = deform->waveparms[3];
6979 // this is how a divisor of vertex influence on deformation
6980 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6981 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6982 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6984 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6985 for (j = 0;j < surface->num_vertices;j++)
6987 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6988 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6989 // if the wavefunc depends on time, evaluate it per-vertex
6992 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6993 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6995 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6998 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6999 rsurface.vertex3f_bufferobject = 0;
7000 rsurface.vertex3f_bufferoffset = 0;
7002 case Q3DEFORM_BULGE:
7003 // deform vertex array to make the surface have moving bulges
7004 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7006 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7007 for (j = 0;j < surface->num_vertices;j++)
7009 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
7010 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
7013 rsurface.vertex3f = rsurface.array_deformedvertex3f;
7014 rsurface.vertex3f_bufferobject = 0;
7015 rsurface.vertex3f_bufferoffset = 0;
7018 // deform vertex array
7019 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
7020 VectorScale(deform->parms, scale, waveparms);
7021 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7023 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7024 for (j = 0;j < surface->num_vertices;j++)
7025 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
7027 rsurface.vertex3f = rsurface.array_deformedvertex3f;
7028 rsurface.vertex3f_bufferobject = 0;
7029 rsurface.vertex3f_bufferoffset = 0;
7033 // generate texcoords based on the chosen texcoord source
7034 switch(rsurface.texture->tcgen.tcgen)
7037 case Q3TCGEN_TEXTURE:
7038 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7039 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
7040 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
7042 case Q3TCGEN_LIGHTMAP:
7043 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
7044 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7045 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7047 case Q3TCGEN_VECTOR:
7048 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7050 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7051 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)
7053 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
7054 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
7057 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7058 rsurface.texcoordtexture2f_bufferobject = 0;
7059 rsurface.texcoordtexture2f_bufferoffset = 0;
7061 case Q3TCGEN_ENVIRONMENT:
7062 // make environment reflections using a spheremap
7063 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7065 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7066 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
7067 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
7068 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
7069 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
7071 // identical to Q3A's method, but executed in worldspace so
7072 // carried models can be shiny too
7074 float viewer[3], d, reflected[3], worldreflected[3];
7076 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
7077 // VectorNormalize(viewer);
7079 d = DotProduct(normal, viewer);
7081 reflected[0] = normal[0]*2*d - viewer[0];
7082 reflected[1] = normal[1]*2*d - viewer[1];
7083 reflected[2] = normal[2]*2*d - viewer[2];
7084 // note: this is proportinal to viewer, so we can normalize later
7086 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7087 VectorNormalize(worldreflected);
7089 // note: this sphere map only uses world x and z!
7090 // so positive and negative y will LOOK THE SAME.
7091 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7092 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7095 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7096 rsurface.texcoordtexture2f_bufferobject = 0;
7097 rsurface.texcoordtexture2f_bufferoffset = 0;
7100 // the only tcmod that needs software vertex processing is turbulent, so
7101 // check for it here and apply the changes if needed
7102 // and we only support that as the first one
7103 // (handling a mixture of turbulent and other tcmods would be problematic
7104 // without punting it entirely to a software path)
7105 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7107 amplitude = rsurface.texture->tcmods[0].parms[1];
7108 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7109 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7111 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7112 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)
7114 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7115 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7118 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7119 rsurface.texcoordtexture2f_bufferobject = 0;
7120 rsurface.texcoordtexture2f_bufferoffset = 0;
7122 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
7123 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7124 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7125 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7128 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7131 const msurface_t *surface = texturesurfacelist[0];
7132 const msurface_t *surface2;
7137 // TODO: lock all array ranges before render, rather than on each surface
7138 if (texturenumsurfaces == 1)
7140 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7141 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);
7143 else if (r_batchmode.integer == 2)
7145 #define MAXBATCHTRIANGLES 4096
7146 int batchtriangles = 0;
7147 int batchelements[MAXBATCHTRIANGLES*3];
7148 for (i = 0;i < texturenumsurfaces;i = j)
7150 surface = texturesurfacelist[i];
7152 if (surface->num_triangles > MAXBATCHTRIANGLES)
7154 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);
7157 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7158 batchtriangles = surface->num_triangles;
7159 firstvertex = surface->num_firstvertex;
7160 endvertex = surface->num_firstvertex + surface->num_vertices;
7161 for (;j < texturenumsurfaces;j++)
7163 surface2 = texturesurfacelist[j];
7164 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7166 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7167 batchtriangles += surface2->num_triangles;
7168 firstvertex = min(firstvertex, surface2->num_firstvertex);
7169 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7171 surface2 = texturesurfacelist[j-1];
7172 numvertices = endvertex - firstvertex;
7173 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7176 else if (r_batchmode.integer == 1)
7178 for (i = 0;i < texturenumsurfaces;i = j)
7180 surface = texturesurfacelist[i];
7181 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7182 if (texturesurfacelist[j] != surface2)
7184 surface2 = texturesurfacelist[j-1];
7185 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7186 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7187 GL_LockArrays(surface->num_firstvertex, numvertices);
7188 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7193 for (i = 0;i < texturenumsurfaces;i++)
7195 surface = texturesurfacelist[i];
7196 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7197 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);
7202 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
7204 int i, planeindex, vertexindex;
7208 r_waterstate_waterplane_t *p, *bestp;
7209 const msurface_t *surface;
7210 if (r_waterstate.renderingscene)
7212 for (i = 0;i < texturenumsurfaces;i++)
7214 surface = texturesurfacelist[i];
7215 if (lightmaptexunit >= 0)
7216 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7217 if (deluxemaptexunit >= 0)
7218 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7219 // pick the closest matching water plane
7222 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7225 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7227 Matrix4x4_Transform(&rsurface.matrix, v, vert);
7228 d += fabs(PlaneDiff(vert, &p->plane));
7230 if (bestd > d || !bestp)
7238 if (refractiontexunit >= 0)
7239 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
7240 if (reflectiontexunit >= 0)
7241 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
7245 if (refractiontexunit >= 0)
7246 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
7247 if (reflectiontexunit >= 0)
7248 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
7250 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7251 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);
7255 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
7259 const msurface_t *surface = texturesurfacelist[0];
7260 const msurface_t *surface2;
7265 // TODO: lock all array ranges before render, rather than on each surface
7266 if (texturenumsurfaces == 1)
7268 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7269 if (deluxemaptexunit >= 0)
7270 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7271 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7272 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);
7274 else if (r_batchmode.integer == 2)
7276 #define MAXBATCHTRIANGLES 4096
7277 int batchtriangles = 0;
7278 int batchelements[MAXBATCHTRIANGLES*3];
7279 for (i = 0;i < texturenumsurfaces;i = j)
7281 surface = texturesurfacelist[i];
7282 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7283 if (deluxemaptexunit >= 0)
7284 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7286 if (surface->num_triangles > MAXBATCHTRIANGLES)
7288 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);
7291 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7292 batchtriangles = surface->num_triangles;
7293 firstvertex = surface->num_firstvertex;
7294 endvertex = surface->num_firstvertex + surface->num_vertices;
7295 for (;j < texturenumsurfaces;j++)
7297 surface2 = texturesurfacelist[j];
7298 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7300 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7301 batchtriangles += surface2->num_triangles;
7302 firstvertex = min(firstvertex, surface2->num_firstvertex);
7303 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7305 surface2 = texturesurfacelist[j-1];
7306 numvertices = endvertex - firstvertex;
7307 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7310 else if (r_batchmode.integer == 1)
7313 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
7314 for (i = 0;i < texturenumsurfaces;i = j)
7316 surface = texturesurfacelist[i];
7317 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7318 if (texturesurfacelist[j] != surface2)
7320 Con_Printf(" %i", j - i);
7323 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
7325 for (i = 0;i < texturenumsurfaces;i = j)
7327 surface = texturesurfacelist[i];
7328 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7329 if (deluxemaptexunit >= 0)
7330 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7331 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7332 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
7335 Con_Printf(" %i", j - i);
7337 surface2 = texturesurfacelist[j-1];
7338 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7339 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7340 GL_LockArrays(surface->num_firstvertex, numvertices);
7341 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7349 for (i = 0;i < texturenumsurfaces;i++)
7351 surface = texturesurfacelist[i];
7352 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7353 if (deluxemaptexunit >= 0)
7354 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7355 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7356 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);
7361 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7364 int texturesurfaceindex;
7365 if (r_showsurfaces.integer == 2)
7367 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7369 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7370 for (j = 0;j < surface->num_triangles;j++)
7372 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7373 GL_Color(f, f, f, 1);
7374 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7380 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7382 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7383 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7384 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);
7385 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7386 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);
7391 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7393 int texturesurfaceindex;
7397 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7399 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7400 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)
7408 rsurface.lightmapcolor4f = rsurface.array_color4f;
7409 rsurface.lightmapcolor4f_bufferobject = 0;
7410 rsurface.lightmapcolor4f_bufferoffset = 0;
7413 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7415 int texturesurfaceindex;
7421 if (rsurface.lightmapcolor4f)
7423 // generate color arrays for the surfaces in this list
7424 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7426 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7427 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)
7429 f = RSurf_FogVertex(v);
7439 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7441 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7442 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)
7444 f = RSurf_FogVertex(v);
7452 rsurface.lightmapcolor4f = rsurface.array_color4f;
7453 rsurface.lightmapcolor4f_bufferobject = 0;
7454 rsurface.lightmapcolor4f_bufferoffset = 0;
7457 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7459 int texturesurfaceindex;
7465 if (!rsurface.lightmapcolor4f)
7467 // generate color arrays for the surfaces in this list
7468 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7470 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7471 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)
7473 f = RSurf_FogVertex(v);
7474 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7475 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7476 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7480 rsurface.lightmapcolor4f = rsurface.array_color4f;
7481 rsurface.lightmapcolor4f_bufferobject = 0;
7482 rsurface.lightmapcolor4f_bufferoffset = 0;
7485 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7487 int texturesurfaceindex;
7491 if (!rsurface.lightmapcolor4f)
7493 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7495 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7496 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)
7504 rsurface.lightmapcolor4f = rsurface.array_color4f;
7505 rsurface.lightmapcolor4f_bufferobject = 0;
7506 rsurface.lightmapcolor4f_bufferoffset = 0;
7509 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7511 int texturesurfaceindex;
7515 if (!rsurface.lightmapcolor4f)
7517 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7519 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7520 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)
7522 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7523 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7524 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7528 rsurface.lightmapcolor4f = rsurface.array_color4f;
7529 rsurface.lightmapcolor4f_bufferobject = 0;
7530 rsurface.lightmapcolor4f_bufferoffset = 0;
7533 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7536 rsurface.lightmapcolor4f = NULL;
7537 rsurface.lightmapcolor4f_bufferobject = 0;
7538 rsurface.lightmapcolor4f_bufferoffset = 0;
7539 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7540 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7541 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7542 GL_Color(r, g, b, a);
7543 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7546 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7548 // TODO: optimize applyfog && applycolor case
7549 // just apply fog if necessary, and tint the fog color array if necessary
7550 rsurface.lightmapcolor4f = NULL;
7551 rsurface.lightmapcolor4f_bufferobject = 0;
7552 rsurface.lightmapcolor4f_bufferoffset = 0;
7553 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7554 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7555 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7556 GL_Color(r, g, b, a);
7557 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7560 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7562 int texturesurfaceindex;
7566 if (texturesurfacelist[0]->lightmapinfo)
7568 // generate color arrays for the surfaces in this list
7569 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7571 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7572 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7574 if (surface->lightmapinfo->samples)
7576 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7577 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7578 VectorScale(lm, scale, c);
7579 if (surface->lightmapinfo->styles[1] != 255)
7581 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7583 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7584 VectorMA(c, scale, lm, c);
7585 if (surface->lightmapinfo->styles[2] != 255)
7588 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7589 VectorMA(c, scale, lm, c);
7590 if (surface->lightmapinfo->styles[3] != 255)
7593 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7594 VectorMA(c, scale, lm, c);
7604 rsurface.lightmapcolor4f = rsurface.array_color4f;
7605 rsurface.lightmapcolor4f_bufferobject = 0;
7606 rsurface.lightmapcolor4f_bufferoffset = 0;
7610 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7611 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7612 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7614 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7615 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7616 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7617 GL_Color(r, g, b, a);
7618 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7621 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7623 int texturesurfaceindex;
7630 vec3_t ambientcolor;
7631 vec3_t diffusecolor;
7635 VectorCopy(rsurface.modellight_lightdir, lightdir);
7636 f = 0.5f * r_refdef.lightmapintensity;
7637 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7638 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7639 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7640 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7641 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7642 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7644 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7646 // generate color arrays for the surfaces in this list
7647 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7649 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7650 int numverts = surface->num_vertices;
7651 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7652 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7653 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7654 // q3-style directional shading
7655 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7657 if ((f = DotProduct(n, lightdir)) > 0)
7658 VectorMA(ambientcolor, f, diffusecolor, c);
7660 VectorCopy(ambientcolor, c);
7668 rsurface.lightmapcolor4f = rsurface.array_color4f;
7669 rsurface.lightmapcolor4f_bufferobject = 0;
7670 rsurface.lightmapcolor4f_bufferoffset = 0;
7671 *applycolor = false;
7675 *r = ambientcolor[0];
7676 *g = ambientcolor[1];
7677 *b = ambientcolor[2];
7678 rsurface.lightmapcolor4f = NULL;
7679 rsurface.lightmapcolor4f_bufferobject = 0;
7680 rsurface.lightmapcolor4f_bufferoffset = 0;
7684 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7686 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7687 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7688 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7689 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7690 GL_Color(r, g, b, a);
7691 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7694 void RSurf_SetupDepthAndCulling(void)
7696 // submodels are biased to avoid z-fighting with world surfaces that they
7697 // may be exactly overlapping (avoids z-fighting artifacts on certain
7698 // doors and things in Quake maps)
7699 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7700 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7701 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7702 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7705 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7707 // transparent sky would be ridiculous
7708 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7710 R_SetupGenericShader(false);
7711 skyrenderlater = true;
7712 RSurf_SetupDepthAndCulling();
7714 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7715 // skymasking on them, and Quake3 never did sky masking (unlike
7716 // software Quake and software Quake2), so disable the sky masking
7717 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7718 // and skymasking also looks very bad when noclipping outside the
7719 // level, so don't use it then either.
7720 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7722 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7723 R_Mesh_ColorPointer(NULL, 0, 0);
7724 R_Mesh_ResetTextureState();
7725 if (skyrendermasked)
7727 R_SetupDepthOrShadowShader();
7728 // depth-only (masking)
7729 GL_ColorMask(0,0,0,0);
7730 // just to make sure that braindead drivers don't draw
7731 // anything despite that colormask...
7732 GL_BlendFunc(GL_ZERO, GL_ONE);
7736 R_SetupGenericShader(false);
7738 GL_BlendFunc(GL_ONE, GL_ZERO);
7740 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7741 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7742 if (skyrendermasked)
7743 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7745 R_Mesh_ResetTextureState();
7746 GL_Color(1, 1, 1, 1);
7749 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
7750 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
7751 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
7753 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7756 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7757 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7758 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7759 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7760 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7761 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7762 if (rsurface.texture->backgroundcurrentskinframe)
7764 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7765 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7766 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7767 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7769 if (rsurface.texture->colormapping)
7771 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7772 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7774 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7775 if (r_shadow_usingdeferredprepass)
7777 R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture));
7778 R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture));
7780 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7781 R_Mesh_ColorPointer(NULL, 0, 0);
7783 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7785 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass)
7787 // render background
7788 GL_BlendFunc(GL_ONE, GL_ZERO);
7790 GL_AlphaTest(false);
7792 GL_Color(1, 1, 1, 1);
7793 R_Mesh_ColorPointer(NULL, 0, 0);
7795 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7796 if (r_glsl_permutation)
7798 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7799 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7800 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7801 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7802 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7803 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7804 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);
7806 GL_LockArrays(0, 0);
7808 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7809 GL_DepthMask(false);
7810 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7811 R_Mesh_ColorPointer(NULL, 0, 0);
7813 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7814 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7815 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7818 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
7819 if (!r_glsl_permutation)
7822 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7823 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7824 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7825 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7826 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7828 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7830 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7832 GL_BlendFunc(GL_ONE, GL_ZERO);
7834 GL_AlphaTest(false);
7838 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7839 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7840 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7843 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7845 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7846 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);
7848 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7852 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7853 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);
7855 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7857 GL_LockArrays(0, 0);
7860 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7862 // OpenGL 1.3 path - anything not completely ancient
7863 int texturesurfaceindex;
7864 qboolean applycolor;
7868 const texturelayer_t *layer;
7869 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7871 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7874 int layertexrgbscale;
7875 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7877 if (layerindex == 0)
7881 GL_AlphaTest(false);
7882 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7885 GL_DepthMask(layer->depthmask && writedepth);
7886 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7887 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7889 layertexrgbscale = 4;
7890 VectorScale(layer->color, 0.25f, layercolor);
7892 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7894 layertexrgbscale = 2;
7895 VectorScale(layer->color, 0.5f, layercolor);
7899 layertexrgbscale = 1;
7900 VectorScale(layer->color, 1.0f, layercolor);
7902 layercolor[3] = layer->color[3];
7903 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7904 R_Mesh_ColorPointer(NULL, 0, 0);
7905 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7906 switch (layer->type)
7908 case TEXTURELAYERTYPE_LITTEXTURE:
7909 memset(&m, 0, sizeof(m));
7910 m.tex[0] = R_GetTexture(r_texture_white);
7911 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7912 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7913 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7914 m.tex[1] = R_GetTexture(layer->texture);
7915 m.texmatrix[1] = layer->texmatrix;
7916 m.texrgbscale[1] = layertexrgbscale;
7917 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7918 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7919 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7920 R_Mesh_TextureState(&m);
7921 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7922 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7923 else if (rsurface.uselightmaptexture)
7924 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7926 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7928 case TEXTURELAYERTYPE_TEXTURE:
7929 memset(&m, 0, sizeof(m));
7930 m.tex[0] = R_GetTexture(layer->texture);
7931 m.texmatrix[0] = layer->texmatrix;
7932 m.texrgbscale[0] = layertexrgbscale;
7933 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7934 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7935 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7936 R_Mesh_TextureState(&m);
7937 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7939 case TEXTURELAYERTYPE_FOG:
7940 memset(&m, 0, sizeof(m));
7941 m.texrgbscale[0] = layertexrgbscale;
7944 m.tex[0] = R_GetTexture(layer->texture);
7945 m.texmatrix[0] = layer->texmatrix;
7946 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7947 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7948 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7950 R_Mesh_TextureState(&m);
7951 // generate a color array for the fog pass
7952 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7953 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7959 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7960 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)
7962 f = 1 - RSurf_FogVertex(v);
7963 c[0] = layercolor[0];
7964 c[1] = layercolor[1];
7965 c[2] = layercolor[2];
7966 c[3] = f * layercolor[3];
7969 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7972 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7974 GL_LockArrays(0, 0);
7977 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7979 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7980 GL_AlphaTest(false);
7984 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7986 // OpenGL 1.1 - crusty old voodoo path
7987 int texturesurfaceindex;
7991 const texturelayer_t *layer;
7992 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7994 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7996 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7998 if (layerindex == 0)
8002 GL_AlphaTest(false);
8003 qglDepthFunc(GL_EQUAL);CHECKGLERROR
8006 GL_DepthMask(layer->depthmask && writedepth);
8007 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
8008 R_Mesh_ColorPointer(NULL, 0, 0);
8009 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
8010 switch (layer->type)
8012 case TEXTURELAYERTYPE_LITTEXTURE:
8013 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
8015 // two-pass lit texture with 2x rgbscale
8016 // first the lightmap pass
8017 memset(&m, 0, sizeof(m));
8018 m.tex[0] = R_GetTexture(r_texture_white);
8019 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
8020 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
8021 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
8022 R_Mesh_TextureState(&m);
8023 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8024 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8025 else if (rsurface.uselightmaptexture)
8026 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8028 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8029 GL_LockArrays(0, 0);
8030 // then apply the texture to it
8031 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8032 memset(&m, 0, sizeof(m));
8033 m.tex[0] = R_GetTexture(layer->texture);
8034 m.texmatrix[0] = layer->texmatrix;
8035 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
8036 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
8037 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
8038 R_Mesh_TextureState(&m);
8039 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);
8043 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
8044 memset(&m, 0, sizeof(m));
8045 m.tex[0] = R_GetTexture(layer->texture);
8046 m.texmatrix[0] = layer->texmatrix;
8047 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
8048 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
8049 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
8050 R_Mesh_TextureState(&m);
8051 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8052 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);
8054 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);
8057 case TEXTURELAYERTYPE_TEXTURE:
8058 // singletexture unlit texture with transparency support
8059 memset(&m, 0, sizeof(m));
8060 m.tex[0] = R_GetTexture(layer->texture);
8061 m.texmatrix[0] = layer->texmatrix;
8062 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
8063 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
8064 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
8065 R_Mesh_TextureState(&m);
8066 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);
8068 case TEXTURELAYERTYPE_FOG:
8069 // singletexture fogging
8070 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8073 memset(&m, 0, sizeof(m));
8074 m.tex[0] = R_GetTexture(layer->texture);
8075 m.texmatrix[0] = layer->texmatrix;
8076 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
8077 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
8078 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
8079 R_Mesh_TextureState(&m);
8082 R_Mesh_ResetTextureState();
8083 // generate a color array for the fog pass
8084 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8090 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8091 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)
8093 f = 1 - RSurf_FogVertex(v);
8094 c[0] = layer->color[0];
8095 c[1] = layer->color[1];
8096 c[2] = layer->color[2];
8097 c[3] = f * layer->color[3];
8100 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8103 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8105 GL_LockArrays(0, 0);
8108 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8110 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8111 GL_AlphaTest(false);
8115 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8119 GL_AlphaTest(false);
8120 R_Mesh_ColorPointer(NULL, 0, 0);
8121 R_Mesh_ResetTextureState();
8122 R_SetupGenericShader(false);
8124 if(rsurface.texture && rsurface.texture->currentskinframe)
8126 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8127 c[3] *= rsurface.texture->currentalpha;
8137 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
8139 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8140 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8141 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8144 // brighten it up (as texture value 127 means "unlit")
8145 c[0] *= 2 * r_refdef.view.colorscale;
8146 c[1] *= 2 * r_refdef.view.colorscale;
8147 c[2] *= 2 * r_refdef.view.colorscale;
8149 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8150 c[3] *= r_wateralpha.value;
8152 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8154 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8155 GL_DepthMask(false);
8157 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8159 GL_BlendFunc(GL_ONE, GL_ONE);
8160 GL_DepthMask(false);
8162 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8164 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8165 GL_DepthMask(false);
8167 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8169 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8170 GL_DepthMask(false);
8174 GL_BlendFunc(GL_ONE, GL_ZERO);
8175 GL_DepthMask(writedepth);
8178 rsurface.lightmapcolor4f = NULL;
8180 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8182 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8184 rsurface.lightmapcolor4f = NULL;
8185 rsurface.lightmapcolor4f_bufferobject = 0;
8186 rsurface.lightmapcolor4f_bufferoffset = 0;
8188 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8190 qboolean applycolor = true;
8193 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8195 r_refdef.lightmapintensity = 1;
8196 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8197 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8201 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8203 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8204 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8205 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8208 if(!rsurface.lightmapcolor4f)
8209 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8211 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8212 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8213 if(r_refdef.fogenabled)
8214 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8216 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8217 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8220 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8223 RSurf_SetupDepthAndCulling();
8224 if (r_showsurfaces.integer == 3 && !prepass)
8226 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8229 switch (vid.renderpath)
8231 case RENDERPATH_GL20:
8232 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8234 case RENDERPATH_GL13:
8235 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8237 case RENDERPATH_GL11:
8238 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8244 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8247 RSurf_SetupDepthAndCulling();
8248 if (r_showsurfaces.integer == 3 && !prepass)
8250 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8253 switch (vid.renderpath)
8255 case RENDERPATH_GL20:
8256 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8258 case RENDERPATH_GL13:
8259 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8261 case RENDERPATH_GL11:
8262 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8268 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8271 int texturenumsurfaces, endsurface;
8273 const msurface_t *surface;
8274 const msurface_t *texturesurfacelist[1024];
8276 // if the model is static it doesn't matter what value we give for
8277 // wantnormals and wanttangents, so this logic uses only rules applicable
8278 // to a model, knowing that they are meaningless otherwise
8279 if (ent == r_refdef.scene.worldentity)
8280 RSurf_ActiveWorldEntity();
8281 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8282 RSurf_ActiveModelEntity(ent, false, false);
8285 switch (vid.renderpath)
8287 case RENDERPATH_GL20:
8288 RSurf_ActiveModelEntity(ent, true, true);
8290 case RENDERPATH_GL13:
8291 case RENDERPATH_GL11:
8292 RSurf_ActiveModelEntity(ent, true, false);
8297 for (i = 0;i < numsurfaces;i = j)
8300 surface = rsurface.modelsurfaces + surfacelist[i];
8301 texture = surface->texture;
8302 rsurface.texture = R_GetCurrentTexture(texture);
8303 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8304 // scan ahead until we find a different texture
8305 endsurface = min(i + 1024, numsurfaces);
8306 texturenumsurfaces = 0;
8307 texturesurfacelist[texturenumsurfaces++] = surface;
8308 for (;j < endsurface;j++)
8310 surface = rsurface.modelsurfaces + surfacelist[j];
8311 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8313 texturesurfacelist[texturenumsurfaces++] = surface;
8315 // render the range of surfaces
8316 if (ent == r_refdef.scene.worldentity)
8317 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8319 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8321 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8322 GL_AlphaTest(false);
8325 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
8327 const entity_render_t *queueentity = r_refdef.scene.worldentity;
8331 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8333 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8335 RSurf_SetupDepthAndCulling();
8336 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8337 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8341 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8343 if (!rsurface.texture->currentnumlayers)
8345 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8347 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8349 RSurf_SetupDepthAndCulling();
8350 GL_AlphaTest(false);
8351 R_Mesh_ColorPointer(NULL, 0, 0);
8352 R_Mesh_ResetTextureState();
8353 R_SetupGenericShader(false);
8354 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8356 GL_BlendFunc(GL_ONE, GL_ZERO);
8357 GL_Color(0, 0, 0, 1);
8358 GL_DepthTest(writedepth);
8359 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8361 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8363 RSurf_SetupDepthAndCulling();
8364 GL_AlphaTest(false);
8365 R_Mesh_ColorPointer(NULL, 0, 0);
8366 R_Mesh_ResetTextureState();
8367 R_SetupGenericShader(false);
8368 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8370 GL_BlendFunc(GL_ONE, GL_ZERO);
8372 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8374 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8375 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8376 else if (!rsurface.texture->currentnumlayers)
8378 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8380 // transparent surfaces get pushed off into the transparent queue
8381 int surfacelistindex;
8382 const msurface_t *surface;
8383 vec3_t tempcenter, center;
8384 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8386 surface = texturesurfacelist[surfacelistindex];
8387 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8388 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8389 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8390 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8391 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8396 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8397 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8402 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8406 // break the surface list down into batches by texture and use of lightmapping
8407 for (i = 0;i < numsurfaces;i = j)
8410 // texture is the base texture pointer, rsurface.texture is the
8411 // current frame/skin the texture is directing us to use (for example
8412 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8413 // use skin 1 instead)
8414 texture = surfacelist[i]->texture;
8415 rsurface.texture = R_GetCurrentTexture(texture);
8416 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8417 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8419 // if this texture is not the kind we want, skip ahead to the next one
8420 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8424 // simply scan ahead until we find a different texture or lightmap state
8425 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8427 // render the range of surfaces
8428 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
8432 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
8437 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8439 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8441 RSurf_SetupDepthAndCulling();
8442 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8443 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8447 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8449 if (!rsurface.texture->currentnumlayers)
8451 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8453 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8455 RSurf_SetupDepthAndCulling();
8456 GL_AlphaTest(false);
8457 R_Mesh_ColorPointer(NULL, 0, 0);
8458 R_Mesh_ResetTextureState();
8459 R_SetupGenericShader(false);
8460 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8462 GL_BlendFunc(GL_ONE, GL_ZERO);
8463 GL_Color(0, 0, 0, 1);
8464 GL_DepthTest(writedepth);
8465 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8467 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8469 RSurf_SetupDepthAndCulling();
8470 GL_AlphaTest(false);
8471 R_Mesh_ColorPointer(NULL, 0, 0);
8472 R_Mesh_ResetTextureState();
8473 R_SetupGenericShader(false);
8474 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8476 GL_BlendFunc(GL_ONE, GL_ZERO);
8478 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8480 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8481 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8482 else if (!rsurface.texture->currentnumlayers)
8484 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8486 // transparent surfaces get pushed off into the transparent queue
8487 int surfacelistindex;
8488 const msurface_t *surface;
8489 vec3_t tempcenter, center;
8490 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8492 surface = texturesurfacelist[surfacelistindex];
8493 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8494 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8495 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8496 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8497 if (queueentity->transparent_offset) // transparent offset
8499 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8500 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8501 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8503 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8508 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8509 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8514 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8518 // break the surface list down into batches by texture and use of lightmapping
8519 for (i = 0;i < numsurfaces;i = j)
8522 // texture is the base texture pointer, rsurface.texture is the
8523 // current frame/skin the texture is directing us to use (for example
8524 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8525 // use skin 1 instead)
8526 texture = surfacelist[i]->texture;
8527 rsurface.texture = R_GetCurrentTexture(texture);
8528 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8529 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8531 // if this texture is not the kind we want, skip ahead to the next one
8532 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8536 // simply scan ahead until we find a different texture or lightmap state
8537 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8539 // render the range of surfaces
8540 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
8544 float locboxvertex3f[6*4*3] =
8546 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8547 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8548 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8549 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8550 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8551 1,0,0, 0,0,0, 0,1,0, 1,1,0
8554 unsigned short locboxelements[6*2*3] =
8564 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8567 cl_locnode_t *loc = (cl_locnode_t *)ent;
8569 float vertex3f[6*4*3];
8571 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8572 GL_DepthMask(false);
8573 GL_DepthRange(0, 1);
8574 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8576 GL_CullFace(GL_NONE);
8577 R_Mesh_Matrix(&identitymatrix);
8579 R_Mesh_VertexPointer(vertex3f, 0, 0);
8580 R_Mesh_ColorPointer(NULL, 0, 0);
8581 R_Mesh_ResetTextureState();
8582 R_SetupGenericShader(false);
8585 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8586 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8587 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8588 surfacelist[0] < 0 ? 0.5f : 0.125f);
8590 if (VectorCompare(loc->mins, loc->maxs))
8592 VectorSet(size, 2, 2, 2);
8593 VectorMA(loc->mins, -0.5f, size, mins);
8597 VectorCopy(loc->mins, mins);
8598 VectorSubtract(loc->maxs, loc->mins, size);
8601 for (i = 0;i < 6*4*3;)
8602 for (j = 0;j < 3;j++, i++)
8603 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8605 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8608 void R_DrawLocs(void)
8611 cl_locnode_t *loc, *nearestloc;
8613 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8614 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8616 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8617 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8621 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8623 if (decalsystem->decals)
8624 Mem_Free(decalsystem->decals);
8625 memset(decalsystem, 0, sizeof(*decalsystem));
8628 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)
8635 // expand or initialize the system
8636 if (decalsystem->maxdecals <= decalsystem->numdecals)
8638 decalsystem_t old = *decalsystem;
8639 qboolean useshortelements;
8640 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8641 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8642 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)));
8643 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8644 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8645 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8646 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8647 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8648 if (decalsystem->numdecals)
8649 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8651 Mem_Free(old.decals);
8652 for (i = 0;i < decalsystem->maxdecals*3;i++)
8653 decalsystem->element3i[i] = i;
8654 if (useshortelements)
8655 for (i = 0;i < decalsystem->maxdecals*3;i++)
8656 decalsystem->element3s[i] = i;
8659 // grab a decal and search for another free slot for the next one
8660 maxdecals = decalsystem->maxdecals;
8661 decals = decalsystem->decals;
8662 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8663 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8665 decalsystem->freedecal = i;
8666 if (decalsystem->numdecals <= i)
8667 decalsystem->numdecals = i + 1;
8669 // initialize the decal
8671 decal->triangleindex = triangleindex;
8672 decal->surfaceindex = surfaceindex;
8673 decal->decalsequence = decalsequence;
8674 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8675 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8676 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8677 decal->color4ub[0][3] = 255;
8678 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8679 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8680 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8681 decal->color4ub[1][3] = 255;
8682 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8683 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8684 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8685 decal->color4ub[2][3] = 255;
8686 decal->vertex3f[0][0] = v0[0];
8687 decal->vertex3f[0][1] = v0[1];
8688 decal->vertex3f[0][2] = v0[2];
8689 decal->vertex3f[1][0] = v1[0];
8690 decal->vertex3f[1][1] = v1[1];
8691 decal->vertex3f[1][2] = v1[2];
8692 decal->vertex3f[2][0] = v2[0];
8693 decal->vertex3f[2][1] = v2[1];
8694 decal->vertex3f[2][2] = v2[2];
8695 decal->texcoord2f[0][0] = t0[0];
8696 decal->texcoord2f[0][1] = t0[1];
8697 decal->texcoord2f[1][0] = t1[0];
8698 decal->texcoord2f[1][1] = t1[1];
8699 decal->texcoord2f[2][0] = t2[0];
8700 decal->texcoord2f[2][1] = t2[1];
8703 extern cvar_t cl_decals_bias;
8704 extern cvar_t cl_decals_models;
8705 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8706 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)
8708 matrix4x4_t projection;
8709 decalsystem_t *decalsystem;
8712 const float *vertex3f;
8713 const msurface_t *surface;
8714 const msurface_t *surfaces;
8715 const int *surfacelist;
8716 const texture_t *texture;
8720 int surfacelistindex;
8723 int decalsurfaceindex;
8728 float localorigin[3];
8729 float localnormal[3];
8740 float points[2][9][3];
8744 decalsystem = &ent->decalsystem;
8746 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8748 R_DecalSystem_Reset(&ent->decalsystem);
8752 if (!model->brush.data_nodes && !cl_decals_models.integer)
8754 if (decalsystem->model)
8755 R_DecalSystem_Reset(decalsystem);
8759 if (decalsystem->model != model)
8760 R_DecalSystem_Reset(decalsystem);
8761 decalsystem->model = model;
8763 RSurf_ActiveModelEntity(ent, false, false);
8765 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8766 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8767 VectorNormalize(localnormal);
8768 localsize = worldsize*rsurface.inversematrixscale;
8769 ilocalsize = 1.0f / localsize;
8770 localmins[0] = localorigin[0] - localsize;
8771 localmins[1] = localorigin[1] - localsize;
8772 localmins[2] = localorigin[2] - localsize;
8773 localmaxs[0] = localorigin[0] + localsize;
8774 localmaxs[1] = localorigin[1] + localsize;
8775 localmaxs[2] = localorigin[2] + localsize;
8777 //VectorCopy(localnormal, planes[4]);
8778 //VectorVectors(planes[4], planes[2], planes[0]);
8779 AnglesFromVectors(angles, localnormal, NULL, false);
8780 AngleVectors(angles, planes[0], planes[2], planes[4]);
8781 VectorNegate(planes[0], planes[1]);
8782 VectorNegate(planes[2], planes[3]);
8783 VectorNegate(planes[4], planes[5]);
8784 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8785 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8786 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8787 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8788 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8789 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8794 matrix4x4_t forwardprojection;
8795 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8796 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8801 float projectionvector[4][3];
8802 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8803 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8804 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8805 projectionvector[0][0] = planes[0][0] * ilocalsize;
8806 projectionvector[0][1] = planes[1][0] * ilocalsize;
8807 projectionvector[0][2] = planes[2][0] * ilocalsize;
8808 projectionvector[1][0] = planes[0][1] * ilocalsize;
8809 projectionvector[1][1] = planes[1][1] * ilocalsize;
8810 projectionvector[1][2] = planes[2][1] * ilocalsize;
8811 projectionvector[2][0] = planes[0][2] * ilocalsize;
8812 projectionvector[2][1] = planes[1][2] * ilocalsize;
8813 projectionvector[2][2] = planes[2][2] * ilocalsize;
8814 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8815 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8816 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8817 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8821 dynamic = model->surfmesh.isanimated;
8822 vertex3f = rsurface.modelvertex3f;
8823 numsurfacelist = model->nummodelsurfaces;
8824 surfacelist = model->sortedmodelsurfaces;
8825 surfaces = model->data_surfaces;
8826 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8828 surfaceindex = surfacelist[surfacelistindex];
8829 surface = surfaces + surfaceindex;
8830 // skip transparent surfaces
8831 texture = surface->texture;
8832 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8834 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8836 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8838 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8839 numvertices = surface->num_vertices;
8840 numtriangles = surface->num_triangles;
8841 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8843 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8845 index = 3*e[cornerindex];
8846 VectorCopy(vertex3f + index, v[cornerindex]);
8849 //TriangleNormal(v[0], v[1], v[2], normal);
8850 //if (DotProduct(normal, localnormal) < 0.0f)
8852 // clip by each of the box planes formed from the projection matrix
8853 // if anything survives, we emit the decal
8854 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]);
8857 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]);
8860 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]);
8863 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]);
8866 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]);
8869 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]);
8872 // some part of the triangle survived, so we have to accept it...
8875 // dynamic always uses the original triangle
8877 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8879 index = 3*e[cornerindex];
8880 VectorCopy(vertex3f + index, v[cornerindex]);
8883 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8885 // convert vertex positions to texcoords
8886 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8887 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8888 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8889 // calculate distance fade from the projection origin
8890 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8891 f = bound(0.0f, f, 1.0f);
8892 c[cornerindex][0] = r * f;
8893 c[cornerindex][1] = g * f;
8894 c[cornerindex][2] = b * f;
8895 c[cornerindex][3] = 1.0f;
8896 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8899 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);
8901 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8902 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);
8907 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8908 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)
8910 int renderentityindex;
8913 entity_render_t *ent;
8915 if (!cl_decals_newsystem.integer)
8918 worldmins[0] = worldorigin[0] - worldsize;
8919 worldmins[1] = worldorigin[1] - worldsize;
8920 worldmins[2] = worldorigin[2] - worldsize;
8921 worldmaxs[0] = worldorigin[0] + worldsize;
8922 worldmaxs[1] = worldorigin[1] + worldsize;
8923 worldmaxs[2] = worldorigin[2] + worldsize;
8925 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8927 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8929 ent = r_refdef.scene.entities[renderentityindex];
8930 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8933 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8937 typedef struct r_decalsystem_splatqueue_s
8946 r_decalsystem_splatqueue_t;
8948 int r_decalsystem_numqueued = 0;
8949 #define MAX_DECALSYSTEM_QUEUE 1024
8950 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8952 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)
8954 r_decalsystem_splatqueue_t *queue;
8956 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8959 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8960 VectorCopy(worldorigin, queue->worldorigin);
8961 VectorCopy(worldnormal, queue->worldnormal);
8962 Vector4Set(queue->color, r, g, b, a);
8963 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8964 queue->worldsize = worldsize;
8965 queue->decalsequence = cl.decalsequence++;
8968 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8971 r_decalsystem_splatqueue_t *queue;
8973 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8974 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);
8975 r_decalsystem_numqueued = 0;
8978 extern cvar_t cl_decals_max;
8979 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8982 decalsystem_t *decalsystem = &ent->decalsystem;
8989 if (!decalsystem->numdecals)
8992 if (r_showsurfaces.integer)
8995 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8997 R_DecalSystem_Reset(decalsystem);
9001 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
9002 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
9004 if (decalsystem->lastupdatetime)
9005 frametime = (cl.time - decalsystem->lastupdatetime);
9008 decalsystem->lastupdatetime = cl.time;
9009 decal = decalsystem->decals;
9010 numdecals = decalsystem->numdecals;
9012 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9014 if (decal->color4ub[0][3])
9016 decal->lived += frametime;
9017 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
9019 memset(decal, 0, sizeof(*decal));
9020 if (decalsystem->freedecal > i)
9021 decalsystem->freedecal = i;
9025 decal = decalsystem->decals;
9026 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
9029 // collapse the array by shuffling the tail decals into the gaps
9032 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
9033 decalsystem->freedecal++;
9034 if (decalsystem->freedecal == numdecals)
9036 decal[decalsystem->freedecal] = decal[--numdecals];
9039 decalsystem->numdecals = numdecals;
9043 // if there are no decals left, reset decalsystem
9044 R_DecalSystem_Reset(decalsystem);
9048 extern skinframe_t *decalskinframe;
9049 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9052 decalsystem_t *decalsystem = &ent->decalsystem;
9062 const unsigned char *surfacevisible = r_refdef.viewcache.world_surfacevisible;
9065 numdecals = decalsystem->numdecals;
9069 if (r_showsurfaces.integer)
9072 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9074 R_DecalSystem_Reset(decalsystem);
9078 // if the model is static it doesn't matter what value we give for
9079 // wantnormals and wanttangents, so this logic uses only rules applicable
9080 // to a model, knowing that they are meaningless otherwise
9081 if (ent == r_refdef.scene.worldentity)
9082 RSurf_ActiveWorldEntity();
9084 RSurf_ActiveModelEntity(ent, false, false);
9086 decalsystem->lastupdatetime = cl.time;
9087 decal = decalsystem->decals;
9089 fadedelay = cl_decals_time.value;
9090 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9092 // update vertex positions for animated models
9093 v3f = decalsystem->vertex3f;
9094 c4f = decalsystem->color4f;
9095 t2f = decalsystem->texcoord2f;
9096 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9098 if (!decal->color4ub[0][3])
9101 if (decal->surfaceindex >= 0 && !surfacevisible[decal->surfaceindex])
9104 // update color values for fading decals
9105 if (decal->lived >= cl_decals_time.value)
9107 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9108 alpha *= (1.0f/255.0f);
9111 alpha = 1.0f/255.0f;
9113 c4f[ 0] = decal->color4ub[0][0] * alpha;
9114 c4f[ 1] = decal->color4ub[0][1] * alpha;
9115 c4f[ 2] = decal->color4ub[0][2] * alpha;
9117 c4f[ 4] = decal->color4ub[1][0] * alpha;
9118 c4f[ 5] = decal->color4ub[1][1] * alpha;
9119 c4f[ 6] = decal->color4ub[1][2] * alpha;
9121 c4f[ 8] = decal->color4ub[2][0] * alpha;
9122 c4f[ 9] = decal->color4ub[2][1] * alpha;
9123 c4f[10] = decal->color4ub[2][2] * alpha;
9126 t2f[0] = decal->texcoord2f[0][0];
9127 t2f[1] = decal->texcoord2f[0][1];
9128 t2f[2] = decal->texcoord2f[1][0];
9129 t2f[3] = decal->texcoord2f[1][1];
9130 t2f[4] = decal->texcoord2f[2][0];
9131 t2f[5] = decal->texcoord2f[2][1];
9133 // update vertex positions for animated models
9134 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9136 e = rsurface.modelelement3i + 3*decal->triangleindex;
9137 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9138 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9139 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9143 VectorCopy(decal->vertex3f[0], v3f);
9144 VectorCopy(decal->vertex3f[1], v3f + 3);
9145 VectorCopy(decal->vertex3f[2], v3f + 6);
9156 r_refdef.stats.drawndecals += numtris;
9157 // now render the decals all at once
9158 // (this assumes they all use one particle font texture!)
9159 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);
9160 R_Mesh_ResetTextureState();
9161 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9162 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9163 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9164 R_SetupGenericShader(true);
9165 GL_DepthMask(false);
9166 GL_DepthRange(0, 1);
9167 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9169 GL_CullFace(GL_NONE);
9170 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9171 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
9172 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
9173 GL_LockArrays(0, numtris * 3);
9174 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9175 GL_LockArrays(0, 0);
9179 static void R_DrawModelDecals(void)
9183 // fade faster when there are too many decals
9184 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9185 for (i = 0;i < r_refdef.scene.numentities;i++)
9186 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9188 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9189 for (i = 0;i < r_refdef.scene.numentities;i++)
9190 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9191 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9193 R_DecalSystem_ApplySplatEntitiesQueue();
9195 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9196 for (i = 0;i < r_refdef.scene.numentities;i++)
9197 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9199 r_refdef.stats.totaldecals += numdecals;
9201 if (r_showsurfaces.integer)
9204 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9206 for (i = 0;i < r_refdef.scene.numentities;i++)
9208 if (!r_refdef.viewcache.entityvisible[i])
9210 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9211 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9215 void R_DrawDebugModel(void)
9217 entity_render_t *ent = rsurface.entity;
9218 int i, j, k, l, flagsmask;
9219 const int *elements;
9221 const msurface_t *surface;
9222 dp_model_t *model = ent->model;
9225 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9227 R_Mesh_ColorPointer(NULL, 0, 0);
9228 R_Mesh_ResetTextureState();
9229 R_SetupGenericShader(false);
9230 GL_DepthRange(0, 1);
9231 GL_DepthTest(!r_showdisabledepthtest.integer);
9232 GL_DepthMask(false);
9233 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9235 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
9237 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
9238 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
9240 if (brush->colbrushf && brush->colbrushf->numtriangles)
9242 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
9243 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);
9244 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
9247 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
9249 if (surface->num_collisiontriangles)
9251 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
9252 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);
9253 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
9258 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9260 if (r_showtris.integer || r_shownormals.integer)
9262 if (r_showdisabledepthtest.integer)
9264 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9265 GL_DepthMask(false);
9269 GL_BlendFunc(GL_ONE, GL_ZERO);
9272 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9274 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9276 rsurface.texture = R_GetCurrentTexture(surface->texture);
9277 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9279 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
9280 if (r_showtris.value > 0)
9282 if (!rsurface.texture->currentlayers->depthmask)
9283 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
9284 else if (ent == r_refdef.scene.worldentity)
9285 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
9287 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
9288 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
9289 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
9290 R_Mesh_ColorPointer(NULL, 0, 0);
9291 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
9292 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9293 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
9294 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);
9295 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9298 if (r_shownormals.value < 0)
9301 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9303 VectorCopy(rsurface.vertex3f + l * 3, v);
9304 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9305 qglVertex3f(v[0], v[1], v[2]);
9306 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
9307 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9308 qglVertex3f(v[0], v[1], v[2]);
9313 if (r_shownormals.value > 0)
9316 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9318 VectorCopy(rsurface.vertex3f + l * 3, v);
9319 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9320 qglVertex3f(v[0], v[1], v[2]);
9321 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
9322 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9323 qglVertex3f(v[0], v[1], v[2]);
9328 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9330 VectorCopy(rsurface.vertex3f + l * 3, v);
9331 GL_Color(0, r_refdef.view.colorscale, 0, 1);
9332 qglVertex3f(v[0], v[1], v[2]);
9333 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
9334 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9335 qglVertex3f(v[0], v[1], v[2]);
9340 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9342 VectorCopy(rsurface.vertex3f + l * 3, v);
9343 GL_Color(0, 0, r_refdef.view.colorscale, 1);
9344 qglVertex3f(v[0], v[1], v[2]);
9345 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
9346 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9347 qglVertex3f(v[0], v[1], v[2]);
9354 rsurface.texture = NULL;
9358 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
9359 int r_maxsurfacelist = 0;
9360 const msurface_t **r_surfacelist = NULL;
9361 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9363 int i, j, endj, f, flagsmask;
9365 dp_model_t *model = r_refdef.scene.worldmodel;
9366 msurface_t *surfaces;
9367 unsigned char *update;
9368 int numsurfacelist = 0;
9372 if (r_maxsurfacelist < model->num_surfaces)
9374 r_maxsurfacelist = model->num_surfaces;
9376 Mem_Free((msurface_t**)r_surfacelist);
9377 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9380 RSurf_ActiveWorldEntity();
9382 surfaces = model->data_surfaces;
9383 update = model->brushq1.lightmapupdateflags;
9385 // update light styles on this submodel
9386 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9388 model_brush_lightstyleinfo_t *style;
9389 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9391 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9393 int *list = style->surfacelist;
9394 style->value = r_refdef.scene.lightstylevalue[style->style];
9395 for (j = 0;j < style->numsurfaces;j++)
9396 update[list[j]] = true;
9401 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9406 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9412 rsurface.uselightmaptexture = false;
9413 rsurface.texture = NULL;
9414 rsurface.rtlight = NULL;
9416 // add visible surfaces to draw list
9417 for (i = 0;i < model->nummodelsurfaces;i++)
9419 j = model->sortedmodelsurfaces[i];
9420 if (r_refdef.viewcache.world_surfacevisible[j])
9421 r_surfacelist[numsurfacelist++] = surfaces + j;
9423 // update lightmaps if needed
9425 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9426 if (r_refdef.viewcache.world_surfacevisible[j])
9428 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9429 // don't do anything if there were no surfaces
9430 if (!numsurfacelist)
9432 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9435 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9436 GL_AlphaTest(false);
9438 // add to stats if desired
9439 if (r_speeds.integer && !skysurfaces && !depthonly)
9441 r_refdef.stats.world_surfaces += numsurfacelist;
9442 for (j = 0;j < numsurfacelist;j++)
9443 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9446 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9449 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9451 int i, j, endj, f, flagsmask;
9453 dp_model_t *model = ent->model;
9454 msurface_t *surfaces;
9455 unsigned char *update;
9456 int numsurfacelist = 0;
9460 if (r_maxsurfacelist < model->num_surfaces)
9462 r_maxsurfacelist = model->num_surfaces;
9464 Mem_Free((msurface_t **)r_surfacelist);
9465 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9468 // if the model is static it doesn't matter what value we give for
9469 // wantnormals and wanttangents, so this logic uses only rules applicable
9470 // to a model, knowing that they are meaningless otherwise
9471 if (ent == r_refdef.scene.worldentity)
9472 RSurf_ActiveWorldEntity();
9473 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9474 RSurf_ActiveModelEntity(ent, false, false);
9476 RSurf_ActiveModelEntity(ent, true, true);
9478 RSurf_ActiveModelEntity(ent, false, false);
9481 switch (vid.renderpath)
9483 case RENDERPATH_GL20:
9484 RSurf_ActiveModelEntity(ent, true, true);
9486 case RENDERPATH_GL13:
9487 case RENDERPATH_GL11:
9488 RSurf_ActiveModelEntity(ent, true, false);
9493 surfaces = model->data_surfaces;
9494 update = model->brushq1.lightmapupdateflags;
9496 // update light styles
9497 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9499 model_brush_lightstyleinfo_t *style;
9500 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9502 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9504 int *list = style->surfacelist;
9505 style->value = r_refdef.scene.lightstylevalue[style->style];
9506 for (j = 0;j < style->numsurfaces;j++)
9507 update[list[j]] = true;
9512 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9517 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9523 rsurface.uselightmaptexture = false;
9524 rsurface.texture = NULL;
9525 rsurface.rtlight = NULL;
9527 // add visible surfaces to draw list
9528 for (i = 0;i < model->nummodelsurfaces;i++)
9529 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9530 // don't do anything if there were no surfaces
9531 if (!numsurfacelist)
9533 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9536 // update lightmaps if needed
9538 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9540 R_BuildLightMap(ent, surfaces + j);
9541 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9542 GL_AlphaTest(false);
9544 // add to stats if desired
9545 if (r_speeds.integer && !skysurfaces && !depthonly)
9547 r_refdef.stats.entities_surfaces += numsurfacelist;
9548 for (j = 0;j < numsurfacelist;j++)
9549 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9552 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9555 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
9557 static texture_t texture;
9558 static msurface_t surface;
9559 const msurface_t *surfacelist = &surface;
9561 // fake enough texture and surface state to render this geometry
9563 texture.update_lastrenderframe = -1; // regenerate this texture
9564 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9565 texture.currentskinframe = skinframe;
9566 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9567 texture.specularscalemod = 1;
9568 texture.specularpowermod = 1;
9570 surface.texture = &texture;
9571 surface.num_triangles = numtriangles;
9572 surface.num_firsttriangle = firsttriangle;
9573 surface.num_vertices = numvertices;
9574 surface.num_firstvertex = firstvertex;
9577 rsurface.texture = R_GetCurrentTexture(surface.texture);
9578 rsurface.uselightmaptexture = false;
9579 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);