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 ViewTintColor;\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, ViewTintColor, ViewTintColor.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)\n"
793 "varying vec3 LightVector;\n"
796 "#if defined(USEOFFSETMAPPING) || defined(USESPECULAR)\n"
797 "//#if defined(USEOFFSETMAPPING) || defined(USESPECULAR) || defined(MODE_LIGHTDIRECTION) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
798 "#define USEEYEVECTOR\n"
799 "varying vec3 EyeVector;\n"
802 "varying vec3 EyeVectorModelSpace;\n"
803 "varying float FogPlaneVertexDist;\n"
806 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
807 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
808 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
809 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
812 "#ifdef USEREFLECTION\n"
813 "varying vec4 ModelViewProjectionPosition;\n"
815 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
816 "uniform vec3 LightPosition;\n"
817 "varying vec4 ModelViewPosition;\n"
820 "#ifdef MODE_LIGHTSOURCE\n"
821 "uniform vec3 LightPosition;\n"
823 "uniform vec3 EyePosition;\n"
824 "#ifdef MODE_LIGHTDIRECTION\n"
825 "uniform vec3 LightDir;\n"
827 "uniform vec4 FogPlane;\n"
833 "// vertex shader specific:\n"
834 "#ifdef VERTEX_SHADER\n"
836 "// 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"
838 "#ifdef MODE_DEFERREDGEOMETRY\n"
841 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
842 "#ifdef USEVERTEXTEXTUREBLEND\n"
843 " gl_FrontColor = gl_Color;\n"
844 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
847 " // transform unnormalized eye direction into tangent space\n"
848 "#ifdef USEOFFSETMAPPING\n"
849 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
850 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
851 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
852 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
855 " VectorS = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz).xyz;\n"
856 " VectorT = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz).xyz;\n"
857 " VectorR = normalize(gl_NormalMatrix * gl_MultiTexCoord3.xyz).xyz;\n"
858 " gl_Position = ftransform();\n"
860 "#else // !MODE_DEFERREDGEOMETRY\n"
861 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
864 " ModelViewPosition = gl_ModelViewMatrix * gl_Vertex;\n"
865 " gl_Position = ftransform();\n"
867 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
870 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
871 " gl_FrontColor = gl_Color;\n"
873 " // copy the surface texcoord\n"
874 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
875 "#ifdef USEVERTEXTEXTUREBLEND\n"
876 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
878 "#ifdef USELIGHTMAP\n"
879 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
882 "#ifdef MODE_LIGHTSOURCE\n"
883 " // transform vertex position into light attenuation/cubemap space\n"
884 " // (-1 to +1 across the light box)\n"
885 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
887 "# ifdef USEDIFFUSE\n"
888 " // transform unnormalized light direction into tangent space\n"
889 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
890 " // normalize it per pixel)\n"
891 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
892 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
893 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
894 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
898 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
899 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
900 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
901 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
904 " // transform unnormalized eye direction into tangent space\n"
905 "#ifdef USEEYEVECTOR\n"
907 " vec3 EyeVectorModelSpace;\n"
909 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
910 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
911 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
912 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
916 "#ifndef USEEYEVECTOR\n"
917 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
919 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
922 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
923 " VectorS = gl_MultiTexCoord1.xyz;\n"
924 " VectorT = gl_MultiTexCoord2.xyz;\n"
925 " VectorR = gl_MultiTexCoord3.xyz;\n"
928 "//#if defined(USEREFLECTION)\n"
929 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
930 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
931 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
934 "// transform vertex to camera space, using ftransform to match non-VS\n"
936 " gl_Position = ftransform();\n"
938 "#ifdef USEREFLECTION\n"
939 " ModelViewProjectionPosition = gl_Position;\n"
942 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
943 "#endif // !MODE_DEFERREDGEOMETRY\n"
945 "#endif // VERTEX_SHADER\n"
950 "// fragment shader specific:\n"
951 "#ifdef FRAGMENT_SHADER\n"
953 "uniform sampler2D Texture_Normal;\n"
954 "uniform sampler2D Texture_Color;\n"
955 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
956 "uniform sampler2D Texture_Gloss;\n"
959 "uniform sampler2D Texture_Glow;\n"
961 "#ifdef USEVERTEXTEXTUREBLEND\n"
962 "uniform sampler2D Texture_SecondaryNormal;\n"
963 "uniform sampler2D Texture_SecondaryColor;\n"
964 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
965 "uniform sampler2D Texture_SecondaryGloss;\n"
968 "uniform sampler2D Texture_SecondaryGlow;\n"
971 "#ifdef USECOLORMAPPING\n"
972 "uniform sampler2D Texture_Pants;\n"
973 "uniform sampler2D Texture_Shirt;\n"
976 "uniform sampler2D Texture_FogMask;\n"
978 "#ifdef USELIGHTMAP\n"
979 "uniform sampler2D Texture_Lightmap;\n"
981 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
982 "uniform sampler2D Texture_Deluxemap;\n"
984 "#ifdef USEREFLECTION\n"
985 "uniform sampler2D Texture_Reflection;\n"
988 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
989 "uniform sampler2DRect Texture_ScreenDepth;\n"
990 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
992 "#ifdef USEDEFERREDLIGHTMAP\n"
993 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
994 "uniform sampler2DRect Texture_ScreenSpecular;\n"
997 "uniform myhalf3 Color_Pants;\n"
998 "uniform myhalf3 Color_Shirt;\n"
999 "uniform myhalf3 FogColor;\n"
1002 "uniform float FogRangeRecip;\n"
1003 "uniform float FogPlaneViewDist;\n"
1004 "uniform float FogHeightFade;\n"
1005 "myhalf FogVertex(void)\n"
1008 "#ifdef USEFOGOUTSIDE\n"
1009 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1011 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1013 " return myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1017 "#ifdef USEOFFSETMAPPING\n"
1018 "uniform float OffsetMapping_Scale;\n"
1019 "vec2 OffsetMapping(vec2 TexCoord)\n"
1021 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1022 " // 14 sample relief mapping: linear search and then binary search\n"
1023 " // this basically steps forward a small amount repeatedly until it finds\n"
1024 " // itself inside solid, then jitters forward and back using decreasing\n"
1025 " // amounts to find the impact\n"
1026 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1027 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1028 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1029 " vec3 RT = vec3(TexCoord, 1);\n"
1030 " OffsetVector *= 0.1;\n"
1031 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1032 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1033 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1034 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1035 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1036 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1037 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1038 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1039 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1040 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1041 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1042 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1043 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1044 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1047 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1048 " // this basically moves forward the full distance, and then backs up based\n"
1049 " // on height of samples\n"
1050 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1051 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1052 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1053 " TexCoord += OffsetVector;\n"
1054 " OffsetVector *= 0.333;\n"
1055 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1056 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1057 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1058 " return TexCoord;\n"
1061 "#endif // USEOFFSETMAPPING\n"
1063 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1064 "uniform sampler2D Texture_Attenuation;\n"
1065 "uniform samplerCube Texture_Cube;\n"
1067 "#ifdef USESHADOWMAPRECT\n"
1068 "# ifdef USESHADOWSAMPLER\n"
1069 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1071 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1075 "#ifdef USESHADOWMAP2D\n"
1076 "# ifdef USESHADOWSAMPLER\n"
1077 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1079 "uniform sampler2D Texture_ShadowMap2D;\n"
1083 "#ifdef USESHADOWMAPVSDCT\n"
1084 "uniform samplerCube Texture_CubeProjection;\n"
1087 "#ifdef USESHADOWMAPCUBE\n"
1088 "# ifdef USESHADOWSAMPLER\n"
1089 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1091 "uniform samplerCube Texture_ShadowMapCube;\n"
1095 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1096 "uniform vec2 ShadowMap_TextureScale;\n"
1097 "uniform vec4 ShadowMap_Parameters;\n"
1100 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1101 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1103 " vec3 adir = abs(dir);\n"
1104 "# ifndef USESHADOWMAPVSDCT\n"
1108 " if (adir.x > adir.y)\n"
1110 " if (adir.x > adir.z) // X\n"
1114 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1120 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1125 " if (adir.y > adir.z) // Y\n"
1129 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1135 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1139 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1140 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1141 " stc.z += ShadowMap_Parameters.z;\n"
1144 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1145 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1146 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1147 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1148 " stc.z += ShadowMap_Parameters.z;\n"
1152 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1154 "#ifdef USESHADOWMAPCUBE\n"
1155 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1157 " vec3 adir = abs(dir);\n"
1158 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1162 "# ifdef USESHADOWMAPRECT\n"
1163 "float ShadowMapCompare(vec3 dir)\n"
1165 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1167 "# ifdef USESHADOWSAMPLER\n"
1169 "# ifdef USESHADOWMAPPCF\n"
1170 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1171 " 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"
1173 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1178 "# ifdef USESHADOWMAPPCF\n"
1179 "# if USESHADOWMAPPCF > 1\n"
1180 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1181 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1182 " 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"
1183 " 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"
1184 " 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"
1185 " 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"
1186 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1187 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1189 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1190 " vec2 offset = fract(shadowmaptc.xy);\n"
1191 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1192 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1193 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1194 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1195 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1198 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1206 "# ifdef USESHADOWMAP2D\n"
1207 "float ShadowMapCompare(vec3 dir)\n"
1209 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1212 "# ifdef USESHADOWSAMPLER\n"
1213 "# ifdef USESHADOWMAPPCF\n"
1214 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1215 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1216 " 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"
1218 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1221 "# ifdef USESHADOWMAPPCF\n"
1222 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1223 "# ifdef GL_ARB_texture_gather\n"
1224 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1226 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1228 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1229 " center *= ShadowMap_TextureScale;\n"
1230 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1231 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1232 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1233 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1234 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1235 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1236 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1238 "# ifdef GL_EXT_gpu_shader4\n"
1239 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1241 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1243 "# if USESHADOWMAPPCF > 1\n"
1244 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1245 " center *= ShadowMap_TextureScale;\n"
1246 " 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"
1247 " 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"
1248 " 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"
1249 " 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"
1250 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1251 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1253 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1254 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1255 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1256 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1257 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1258 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1262 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1269 "# ifdef USESHADOWMAPCUBE\n"
1270 "float ShadowMapCompare(vec3 dir)\n"
1272 " // apply depth texture cubemap as light filter\n"
1273 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1275 "# ifdef USESHADOWSAMPLER\n"
1276 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1278 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1283 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1285 "#ifdef MODE_DEFERREDGEOMETRY\n"
1288 "#ifdef USEOFFSETMAPPING\n"
1289 " // apply offsetmapping\n"
1290 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1291 "#define TexCoord TexCoordOffset\n"
1294 "#ifdef USEALPHAKILL\n"
1295 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1299 "#ifdef USEVERTEXTEXTUREBLEND\n"
1300 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1301 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1302 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1303 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1306 "#ifdef USEVERTEXTEXTUREBLEND\n"
1307 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1309 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1312 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1314 "#else // !MODE_DEFERREDGEOMETRY\n"
1315 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1316 "uniform mat4 ViewToLight;\n"
1317 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1318 "uniform vec2 ScreenToDepth;\n"
1319 "uniform myhalf3 DeferredColor_Ambient;\n"
1320 "uniform myhalf3 DeferredColor_Diffuse;\n"
1321 "#ifdef USESPECULAR\n"
1322 "uniform myhalf3 DeferredColor_Specular;\n"
1323 "uniform myhalf SpecularPower;\n"
1327 " // calculate viewspace pixel position\n"
1329 " position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1330 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1331 " // decode viewspace pixel normal\n"
1332 " myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1333 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1334 " // surfacenormal = pixel normal in viewspace\n"
1335 " // LightVector = pixel to light in viewspace\n"
1336 " // CubeVector = position in lightspace\n"
1337 " // eyevector = pixel to view in viewspace\n"
1338 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1339 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1340 "#ifdef USEDIFFUSE\n"
1341 " // calculate diffuse shading\n"
1342 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1343 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1345 "#ifdef USESPECULAR\n"
1346 " // calculate directional shading\n"
1347 " vec3 eyevector = position * -1.0;\n"
1348 "# ifdef USEEXACTSPECULARMATH\n"
1349 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1351 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1352 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1356 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1357 " fade *= ShadowMapCompare(CubeVector);\n"
1360 "#ifdef USEDIFFUSE\n"
1361 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1363 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1365 "#ifdef USESPECULAR\n"
1366 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1368 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1371 "# ifdef USECUBEFILTER\n"
1372 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1373 " gl_FragData[0] *= cubecolor;\n"
1374 " gl_FragData[1] *= cubecolor;\n"
1377 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1378 "#ifdef USEDEFERREDLIGHTMAP\n"
1379 "uniform myhalf3 DeferredMod_Diffuse;\n"
1380 "uniform myhalf3 DeferredMod_Specular;\n"
1382 "uniform myhalf3 Color_Ambient;\n"
1383 "uniform myhalf3 Color_Diffuse;\n"
1384 "uniform myhalf3 Color_Specular;\n"
1385 "uniform myhalf SpecularPower;\n"
1387 "uniform myhalf3 Color_Glow;\n"
1389 "uniform myhalf Alpha;\n"
1390 "#ifdef USEREFLECTION\n"
1391 "uniform vec4 DistortScaleRefractReflect;\n"
1392 "uniform vec4 ScreenScaleRefractReflect;\n"
1393 "uniform vec4 ScreenCenterRefractReflect;\n"
1394 "uniform myhalf4 ReflectColor;\n"
1396 "#ifdef MODE_LIGHTDIRECTION\n"
1397 "uniform myhalf3 LightColor;\n"
1399 "#ifdef MODE_LIGHTSOURCE\n"
1400 "uniform myhalf3 LightColor;\n"
1404 "#ifdef USEOFFSETMAPPING\n"
1405 " // apply offsetmapping\n"
1406 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1407 "#define TexCoord TexCoordOffset\n"
1410 " // combine the diffuse textures (base, pants, shirt)\n"
1411 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1412 "#ifdef USEALPHAKILL\n"
1413 " if (color.a < 0.5)\n"
1416 " color.a *= Alpha;\n"
1417 "#ifdef USECOLORMAPPING\n"
1418 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1420 "#ifdef USEVERTEXTEXTUREBLEND\n"
1421 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1422 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1423 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1424 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1426 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1429 " // get the surface normal\n"
1430 "#ifdef USEVERTEXTEXTUREBLEND\n"
1431 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1433 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1436 " // get the material colors\n"
1437 " myhalf3 diffusetex = color.rgb;\n"
1438 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1439 "# ifdef USEVERTEXTEXTUREBLEND\n"
1440 " myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1442 " myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1449 "#ifdef MODE_LIGHTSOURCE\n"
1450 " // light source\n"
1451 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1452 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1453 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1454 "#ifdef USESPECULAR\n"
1455 "#ifdef USEEXACTSPECULARMATH\n"
1456 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1458 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1459 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1461 " color.rgb += glosstex * (specular * Color_Specular);\n"
1463 " color.rgb *= LightColor;\n"
1464 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1465 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1466 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1468 "# ifdef USECUBEFILTER\n"
1469 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1471 "#endif // MODE_LIGHTSOURCE\n"
1476 "#ifdef MODE_LIGHTDIRECTION\n"
1478 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1479 "#define lightcolor LightColor\n"
1480 "#endif // MODE_LIGHTDIRECTION\n"
1481 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1483 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1484 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1485 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1486 " // convert modelspace light vector to tangentspace\n"
1487 " myhalf3 lightnormal;\n"
1488 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1489 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1490 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1491 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1492 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1493 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1494 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1495 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1496 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1497 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1498 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1499 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1500 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1501 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1502 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1504 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1505 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1506 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1512 "#ifdef MODE_LIGHTMAP\n"
1513 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1514 "#endif // MODE_LIGHTMAP\n"
1515 "#ifdef MODE_VERTEXCOLOR\n"
1516 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1517 "#endif // MODE_VERTEXCOLOR\n"
1518 "#ifdef MODE_FLATCOLOR\n"
1519 " color.rgb = diffusetex * Color_Ambient;\n"
1520 "#endif // MODE_FLATCOLOR\n"
1526 "# ifdef USEDIFFUSE\n"
1527 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1528 "# ifdef USESPECULAR\n"
1529 "# ifdef USEEXACTSPECULARMATH\n"
1530 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1532 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1533 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1535 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1537 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1540 " color.rgb = diffusetex * Color_Ambient;\n"
1544 "#ifdef USEDEFERREDLIGHTMAP\n"
1545 " color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1546 " color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1550 "#ifdef USEVERTEXTEXTUREBLEND\n"
1551 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1553 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1558 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1561 " // 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"
1562 "#ifdef USEREFLECTION\n"
1563 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1564 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1565 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1566 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1567 " // FIXME temporary hack to detect the case that the reflection\n"
1568 " // gets blackened at edges due to leaving the area that contains actual\n"
1570 " // Remove this 'ack once we have a better way to stop this thing from\n"
1572 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1573 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1574 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1575 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1576 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1577 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1580 " gl_FragColor = vec4(color);\n"
1582 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1583 "#endif // !MODE_DEFERREDGEOMETRY\n"
1585 "#endif // FRAGMENT_SHADER\n"
1587 "#endif // !MODE_WATER\n"
1588 "#endif // !MODE_REFRACTION\n"
1589 "#endif // !MODE_BLOOMBLUR\n"
1590 "#endif // !MODE_GENERIC\n"
1591 "#endif // !MODE_POSTPROCESS\n"
1592 "#endif // !MODE_SHOWDEPTH\n"
1593 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1596 typedef struct shaderpermutationinfo_s
1598 const char *pretext;
1601 shaderpermutationinfo_t;
1603 typedef struct shadermodeinfo_s
1605 const char *vertexfilename;
1606 const char *geometryfilename;
1607 const char *fragmentfilename;
1608 const char *pretext;
1613 typedef enum shaderpermutation_e
1615 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1616 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1617 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1618 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1619 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1620 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1621 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1622 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1623 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1624 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1625 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1626 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1627 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1628 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1629 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1630 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1631 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1632 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1633 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1634 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1635 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1636 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1637 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1638 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1639 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
1640 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
1641 SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
1642 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
1644 shaderpermutation_t;
1646 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1647 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1649 {"#define USEDIFFUSE\n", " diffuse"},
1650 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1651 {"#define USEVIEWTINT\n", " viewtint"},
1652 {"#define USECOLORMAPPING\n", " colormapping"},
1653 {"#define USESATURATION\n", " saturation"},
1654 {"#define USEFOGINSIDE\n", " foginside"},
1655 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1656 {"#define USEGAMMARAMPS\n", " gammaramps"},
1657 {"#define USECUBEFILTER\n", " cubefilter"},
1658 {"#define USEGLOW\n", " glow"},
1659 {"#define USEBLOOM\n", " bloom"},
1660 {"#define USESPECULAR\n", " specular"},
1661 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1662 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1663 {"#define USEREFLECTION\n", " reflection"},
1664 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1665 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1666 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1667 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1668 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1669 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1670 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1671 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1672 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1673 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
1674 {"#define USEALPHAKILL\n", " alphakill"},
1677 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1678 typedef enum shadermode_e
1680 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1681 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1682 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1683 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1684 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1685 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1686 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1687 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1688 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1689 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1690 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1691 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1692 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1693 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
1694 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
1699 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1700 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1702 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1703 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1704 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1705 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1706 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1707 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1708 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1709 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1710 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1711 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1712 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1713 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1714 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1715 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1716 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1719 struct r_glsl_permutation_s;
1720 typedef struct r_glsl_permutation_s
1722 /// hash lookup data
1723 struct r_glsl_permutation_s *hashnext;
1725 unsigned int permutation;
1727 /// indicates if we have tried compiling this permutation already
1729 /// 0 if compilation failed
1731 /// locations of detected uniforms in program object, or -1 if not found
1732 int loc_Texture_First;
1733 int loc_Texture_Second;
1734 int loc_Texture_GammaRamps;
1735 int loc_Texture_Normal;
1736 int loc_Texture_Color;
1737 int loc_Texture_Gloss;
1738 int loc_Texture_Glow;
1739 int loc_Texture_SecondaryNormal;
1740 int loc_Texture_SecondaryColor;
1741 int loc_Texture_SecondaryGloss;
1742 int loc_Texture_SecondaryGlow;
1743 int loc_Texture_Pants;
1744 int loc_Texture_Shirt;
1745 int loc_Texture_FogMask;
1746 int loc_Texture_Lightmap;
1747 int loc_Texture_Deluxemap;
1748 int loc_Texture_Attenuation;
1749 int loc_Texture_Cube;
1750 int loc_Texture_Refraction;
1751 int loc_Texture_Reflection;
1752 int loc_Texture_ShadowMapRect;
1753 int loc_Texture_ShadowMapCube;
1754 int loc_Texture_ShadowMap2D;
1755 int loc_Texture_CubeProjection;
1756 int loc_Texture_ScreenDepth;
1757 int loc_Texture_ScreenNormalMap;
1758 int loc_Texture_ScreenDiffuse;
1759 int loc_Texture_ScreenSpecular;
1761 int loc_BloomBlur_Parameters;
1763 int loc_Color_Ambient;
1764 int loc_Color_Diffuse;
1765 int loc_Color_Specular;
1767 int loc_Color_Pants;
1768 int loc_Color_Shirt;
1769 int loc_DeferredColor_Ambient;
1770 int loc_DeferredColor_Diffuse;
1771 int loc_DeferredColor_Specular;
1772 int loc_DeferredMod_Diffuse;
1773 int loc_DeferredMod_Specular;
1774 int loc_DistortScaleRefractReflect;
1775 int loc_EyePosition;
1777 int loc_FogHeightFade;
1779 int loc_FogPlaneViewDist;
1780 int loc_FogRangeRecip;
1783 int loc_LightPosition;
1784 int loc_OffsetMapping_Scale;
1786 int loc_ReflectColor;
1787 int loc_ReflectFactor;
1788 int loc_ReflectOffset;
1789 int loc_RefractColor;
1791 int loc_ScreenCenterRefractReflect;
1792 int loc_ScreenScaleRefractReflect;
1793 int loc_ScreenToDepth;
1794 int loc_ShadowMap_Parameters;
1795 int loc_ShadowMap_TextureScale;
1796 int loc_SpecularPower;
1801 int loc_ViewTintColor;
1802 int loc_ViewToLight;
1804 r_glsl_permutation_t;
1806 #define SHADERPERMUTATION_HASHSIZE 256
1808 /// information about each possible shader permutation
1809 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1810 /// currently selected permutation
1811 r_glsl_permutation_t *r_glsl_permutation;
1812 /// storage for permutations linked in the hash table
1813 memexpandablearray_t r_glsl_permutationarray;
1815 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1817 //unsigned int hashdepth = 0;
1818 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1819 r_glsl_permutation_t *p;
1820 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1822 if (p->mode == mode && p->permutation == permutation)
1824 //if (hashdepth > 10)
1825 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1830 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1832 p->permutation = permutation;
1833 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1834 r_glsl_permutationhash[mode][hashindex] = p;
1835 //if (hashdepth > 10)
1836 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1840 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1843 if (!filename || !filename[0])
1845 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1848 if (printfromdisknotice)
1849 Con_DPrintf("from disk %s... ", filename);
1850 return shaderstring;
1852 else if (!strcmp(filename, "glsl/default.glsl"))
1854 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1855 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1857 return shaderstring;
1860 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1863 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1864 int vertstrings_count = 0;
1865 int geomstrings_count = 0;
1866 int fragstrings_count = 0;
1867 char *vertexstring, *geometrystring, *fragmentstring;
1868 const char *vertstrings_list[32+3];
1869 const char *geomstrings_list[32+3];
1870 const char *fragstrings_list[32+3];
1871 char permutationname[256];
1878 permutationname[0] = 0;
1879 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1880 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1881 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1883 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1885 // the first pretext is which type of shader to compile as
1886 // (later these will all be bound together as a program object)
1887 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1888 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1889 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1891 // the second pretext is the mode (for example a light source)
1892 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1893 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1894 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1895 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1897 // now add all the permutation pretexts
1898 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1900 if (permutation & (1<<i))
1902 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1903 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1904 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1905 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1909 // keep line numbers correct
1910 vertstrings_list[vertstrings_count++] = "\n";
1911 geomstrings_list[geomstrings_count++] = "\n";
1912 fragstrings_list[fragstrings_count++] = "\n";
1916 // now append the shader text itself
1917 vertstrings_list[vertstrings_count++] = vertexstring;
1918 geomstrings_list[geomstrings_count++] = geometrystring;
1919 fragstrings_list[fragstrings_count++] = fragmentstring;
1921 // if any sources were NULL, clear the respective list
1923 vertstrings_count = 0;
1924 if (!geometrystring)
1925 geomstrings_count = 0;
1926 if (!fragmentstring)
1927 fragstrings_count = 0;
1929 // compile the shader program
1930 if (vertstrings_count + geomstrings_count + fragstrings_count)
1931 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1935 qglUseProgramObjectARB(p->program);CHECKGLERROR
1936 // look up all the uniform variable names we care about, so we don't
1937 // have to look them up every time we set them
1939 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1940 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1941 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1942 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1943 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1944 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1945 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1946 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1947 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1948 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1949 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1950 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1951 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1952 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1953 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1954 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1955 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1956 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1957 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1958 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1959 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1960 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1961 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1962 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1963 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
1964 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
1965 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
1966 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
1967 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
1968 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
1969 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1970 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
1971 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
1972 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
1973 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
1974 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1975 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1976 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
1977 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
1978 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
1979 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
1980 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
1981 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1982 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1983 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1984 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
1985 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
1986 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
1987 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1988 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
1989 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1990 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1991 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1992 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1993 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1994 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1995 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1996 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1997 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1998 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1999 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
2000 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
2001 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
2002 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
2003 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
2004 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
2005 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
2006 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
2007 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
2008 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
2009 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
2010 // initialize the samplers to refer to the texture units we use
2011 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
2012 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
2013 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
2014 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
2015 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
2016 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
2017 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
2018 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
2019 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
2020 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
2021 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
2022 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
2023 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
2024 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
2025 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
2026 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
2027 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
2028 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
2029 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
2030 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
2031 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
2032 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
2033 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
2034 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
2035 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
2036 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
2037 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
2038 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
2040 if (developer.integer)
2041 Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
2044 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
2048 Mem_Free(vertexstring);
2050 Mem_Free(geometrystring);
2052 Mem_Free(fragmentstring);
2055 void R_GLSL_Restart_f(void)
2057 unsigned int i, limit;
2058 r_glsl_permutation_t *p;
2059 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
2060 for (i = 0;i < limit;i++)
2062 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
2064 GL_Backend_FreeProgram(p->program);
2065 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
2068 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2071 void R_GLSL_DumpShader_f(void)
2075 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
2078 Con_Printf("failed to write to glsl/default.glsl\n");
2082 FS_Print(file, "/* The engine may define the following macros:\n");
2083 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2084 for (i = 0;i < SHADERMODE_COUNT;i++)
2085 FS_Print(file, shadermodeinfo[i].pretext);
2086 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2087 FS_Print(file, shaderpermutationinfo[i].pretext);
2088 FS_Print(file, "*/\n");
2089 FS_Print(file, builtinshaderstring);
2092 Con_Printf("glsl/default.glsl written\n");
2095 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
2097 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2098 if (r_glsl_permutation != perm)
2100 r_glsl_permutation = perm;
2101 if (!r_glsl_permutation->program)
2103 if (!r_glsl_permutation->compiled)
2104 R_GLSL_CompilePermutation(perm, mode, permutation);
2105 if (!r_glsl_permutation->program)
2107 // remove features until we find a valid permutation
2109 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2111 // reduce i more quickly whenever it would not remove any bits
2112 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2113 if (!(permutation & j))
2116 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2117 if (!r_glsl_permutation->compiled)
2118 R_GLSL_CompilePermutation(perm, mode, permutation);
2119 if (r_glsl_permutation->program)
2122 if (i >= SHADERPERMUTATION_COUNT)
2124 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2125 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2126 qglUseProgramObjectARB(0);CHECKGLERROR
2127 return; // no bit left to clear, entire mode is broken
2132 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2136 void R_SetupGenericShader(qboolean usetexture)
2138 switch(vid.renderpath)
2140 case RENDERPATH_GL20:
2141 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2143 case RENDERPATH_GL13:
2144 case RENDERPATH_GL11:
2149 void R_SetupGenericTwoTextureShader(int texturemode)
2151 switch (vid.renderpath)
2153 case RENDERPATH_GL20:
2154 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))));
2156 case RENDERPATH_GL13:
2157 case RENDERPATH_GL11:
2158 R_Mesh_TexCombine(1, GL_DECAL, GL_DECAL, 1, 1);
2163 void R_SetupDepthOrShadowShader(void)
2165 switch (vid.renderpath)
2167 case RENDERPATH_GL20:
2168 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2170 case RENDERPATH_GL13:
2172 case RENDERPATH_GL11:
2177 void R_SetupShowDepthShader(void)
2179 switch (vid.renderpath)
2181 case RENDERPATH_GL20:
2182 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2184 case RENDERPATH_GL13:
2186 case RENDERPATH_GL11:
2191 extern qboolean r_shadow_usingdeferredprepass;
2192 extern cvar_t r_shadow_deferred_8bitrange;
2193 extern rtexture_t *r_shadow_attenuationgradienttexture;
2194 extern rtexture_t *r_shadow_attenuation2dtexture;
2195 extern rtexture_t *r_shadow_attenuation3dtexture;
2196 extern qboolean r_shadow_usingshadowmaprect;
2197 extern qboolean r_shadow_usingshadowmapcube;
2198 extern qboolean r_shadow_usingshadowmap2d;
2199 extern float r_shadow_shadowmap_texturescale[2];
2200 extern float r_shadow_shadowmap_parameters[4];
2201 extern qboolean r_shadow_shadowmapvsdct;
2202 extern qboolean r_shadow_shadowmapsampler;
2203 extern int r_shadow_shadowmappcf;
2204 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2206 // select a permutation of the lighting shader appropriate to this
2207 // combination of texture, entity, light source, and fogging, only use the
2208 // minimum features necessary to avoid wasting rendering time in the
2209 // fragment shader on features that are not being used
2210 unsigned int permutation = 0;
2211 unsigned int mode = 0;
2212 // TODO: implement geometry-shader based shadow volumes someday
2213 if (r_glsl_offsetmapping.integer)
2215 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2216 if (r_glsl_offsetmapping_reliefmapping.integer)
2217 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2219 if (rsurfacepass == RSURFPASS_BACKGROUND)
2221 // distorted background
2222 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2223 mode = SHADERMODE_WATER;
2225 mode = SHADERMODE_REFRACTION;
2227 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2229 // normalmap (deferred prepass), may use alpha test on diffuse
2230 mode = SHADERMODE_DEFERREDGEOMETRY;
2231 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2232 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2233 if (r_glsl_offsetmapping.integer)
2235 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2236 if (r_glsl_offsetmapping_reliefmapping.integer)
2237 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2240 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2243 mode = SHADERMODE_LIGHTSOURCE;
2244 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2245 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2246 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2247 permutation |= SHADERPERMUTATION_CUBEFILTER;
2248 if (diffusescale > 0)
2249 permutation |= SHADERPERMUTATION_DIFFUSE;
2250 if (specularscale > 0)
2251 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2252 if (r_refdef.fogenabled)
2253 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2254 if (rsurface.texture->colormapping)
2255 permutation |= SHADERPERMUTATION_COLORMAPPING;
2256 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2258 if (r_shadow_usingshadowmaprect)
2259 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2260 if (r_shadow_usingshadowmap2d)
2261 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2262 if (r_shadow_usingshadowmapcube)
2263 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2264 else if(r_shadow_shadowmapvsdct)
2265 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2267 if (r_shadow_shadowmapsampler)
2268 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2269 if (r_shadow_shadowmappcf > 1)
2270 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2271 else if (r_shadow_shadowmappcf)
2272 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2275 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2277 // unshaded geometry (fullbright or ambient model lighting)
2278 mode = SHADERMODE_FLATCOLOR;
2279 ambientscale = diffusescale = specularscale = 0;
2280 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2281 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2282 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2283 permutation |= SHADERPERMUTATION_GLOW;
2284 if (r_refdef.fogenabled)
2285 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2286 if (rsurface.texture->colormapping)
2287 permutation |= SHADERPERMUTATION_COLORMAPPING;
2288 if (r_glsl_offsetmapping.integer)
2290 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2291 if (r_glsl_offsetmapping_reliefmapping.integer)
2292 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2294 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2295 permutation |= SHADERPERMUTATION_REFLECTION;
2297 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2299 // directional model lighting
2300 mode = SHADERMODE_LIGHTDIRECTION;
2301 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2302 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2303 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2304 permutation |= SHADERPERMUTATION_GLOW;
2305 permutation |= SHADERPERMUTATION_DIFFUSE;
2306 if (specularscale > 0)
2307 permutation |= SHADERPERMUTATION_SPECULAR;
2308 if (r_refdef.fogenabled)
2309 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2310 if (rsurface.texture->colormapping)
2311 permutation |= SHADERPERMUTATION_COLORMAPPING;
2312 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2313 permutation |= SHADERPERMUTATION_REFLECTION;
2314 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2315 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2317 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2319 // ambient model lighting
2320 mode = SHADERMODE_LIGHTDIRECTION;
2321 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2322 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2323 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2324 permutation |= SHADERPERMUTATION_GLOW;
2325 if (r_refdef.fogenabled)
2326 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2327 if (rsurface.texture->colormapping)
2328 permutation |= SHADERPERMUTATION_COLORMAPPING;
2329 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2330 permutation |= SHADERPERMUTATION_REFLECTION;
2331 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2332 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2337 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2339 // deluxemapping (light direction texture)
2340 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2341 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2343 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2344 permutation |= SHADERPERMUTATION_DIFFUSE;
2345 if (specularscale > 0)
2346 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2348 else if (r_glsl_deluxemapping.integer >= 2)
2350 // fake deluxemapping (uniform light direction in tangentspace)
2351 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2352 permutation |= SHADERPERMUTATION_DIFFUSE;
2353 if (specularscale > 0)
2354 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2356 else if (rsurface.uselightmaptexture)
2358 // ordinary lightmapping (q1bsp, q3bsp)
2359 mode = SHADERMODE_LIGHTMAP;
2363 // ordinary vertex coloring (q3bsp)
2364 mode = SHADERMODE_VERTEXCOLOR;
2366 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2367 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2368 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2369 permutation |= SHADERPERMUTATION_GLOW;
2370 if (r_refdef.fogenabled)
2371 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2372 if (rsurface.texture->colormapping)
2373 permutation |= SHADERPERMUTATION_COLORMAPPING;
2374 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2375 permutation |= SHADERPERMUTATION_REFLECTION;
2376 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2377 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379 if(permutation & SHADERPERMUTATION_SPECULAR)
2380 if(r_shadow_glossexact.integer)
2381 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2382 if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
2383 permutation |= SHADERPERMUTATION_ALPHAKILL;
2384 R_SetupShader_SetPermutation(mode, permutation);
2385 if (mode == SHADERMODE_LIGHTSOURCE)
2387 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2388 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2389 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
2390 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
2391 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
2393 // additive passes are only darkened by fog, not tinted
2394 if (r_glsl_permutation->loc_FogColor >= 0)
2395 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2396 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]);
2397 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]);
2398 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2402 if (mode == SHADERMODE_FLATCOLOR)
2404 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
2406 else if (mode == SHADERMODE_LIGHTDIRECTION)
2408 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);
2409 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
2410 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
2411 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
2412 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2413 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2414 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]);
2418 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
2419 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2420 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
2421 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2422 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2424 // additive passes are only darkened by fog, not tinted
2425 if (r_glsl_permutation->loc_FogColor >= 0)
2427 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2428 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2430 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2432 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);
2433 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]);
2434 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]);
2435 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2436 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2437 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2438 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2439 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2441 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2442 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
2443 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2444 if (r_glsl_permutation->loc_Color_Pants >= 0)
2446 if (rsurface.texture->currentskinframe->pants)
2447 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2449 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2451 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2453 if (rsurface.texture->currentskinframe->shirt)
2454 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2456 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2458 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]);
2459 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2460 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2461 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2462 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2463 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]);
2467 void R_SetupDeferredLightShader(const rtlight_t *rtlight)
2469 // select a permutation of the lighting shader appropriate to this
2470 // combination of texture, entity, light source, and fogging, only use the
2471 // minimum features necessary to avoid wasting rendering time in the
2472 // fragment shader on features that are not being used
2473 unsigned int permutation = 0;
2474 unsigned int mode = 0;
2475 const float *lightcolorbase = rtlight->currentcolor;
2476 float ambientscale = rtlight->ambientscale;
2477 float diffusescale = rtlight->diffusescale;
2478 float specularscale = rtlight->specularscale;
2479 // this is the location of the light in view space
2480 vec3_t viewlightorigin;
2481 // this transforms from view space (camera) to light space (cubemap)
2482 matrix4x4_t viewtolight;
2483 matrix4x4_t lighttoview;
2484 float viewtolight16f[16];
2485 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2487 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2488 if (rtlight->currentcubemap != r_texture_whitecube)
2489 permutation |= SHADERPERMUTATION_CUBEFILTER;
2490 if (diffusescale > 0)
2491 permutation |= SHADERPERMUTATION_DIFFUSE;
2492 if (specularscale > 0)
2494 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2495 if (r_shadow_glossexact.integer)
2496 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2498 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2500 if (r_shadow_usingshadowmaprect)
2501 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2502 if (r_shadow_usingshadowmap2d)
2503 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2504 if (r_shadow_usingshadowmapcube)
2505 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2506 else if(r_shadow_shadowmapvsdct)
2507 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2509 if (r_shadow_shadowmapsampler)
2510 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2511 if (r_shadow_shadowmappcf > 1)
2512 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2513 else if (r_shadow_shadowmappcf)
2514 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2516 R_SetupShader_SetPermutation(mode, permutation);
2517 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2518 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2519 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2520 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2521 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2522 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight, 1, false, viewtolight16f);
2523 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2524 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2525 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2526 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]);
2527 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]);
2528 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2529 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]);
2532 #define SKINFRAME_HASH 1024
2536 int loadsequence; // incremented each level change
2537 memexpandablearray_t array;
2538 skinframe_t *hash[SKINFRAME_HASH];
2541 r_skinframe_t r_skinframe;
2543 void R_SkinFrame_PrepareForPurge(void)
2545 r_skinframe.loadsequence++;
2546 // wrap it without hitting zero
2547 if (r_skinframe.loadsequence >= 200)
2548 r_skinframe.loadsequence = 1;
2551 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2555 // mark the skinframe as used for the purging code
2556 skinframe->loadsequence = r_skinframe.loadsequence;
2559 void R_SkinFrame_Purge(void)
2563 for (i = 0;i < SKINFRAME_HASH;i++)
2565 for (s = r_skinframe.hash[i];s;s = s->next)
2567 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2569 if (s->merged == s->base)
2571 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2572 R_PurgeTexture(s->stain );s->stain = NULL;
2573 R_PurgeTexture(s->merged);s->merged = NULL;
2574 R_PurgeTexture(s->base );s->base = NULL;
2575 R_PurgeTexture(s->pants );s->pants = NULL;
2576 R_PurgeTexture(s->shirt );s->shirt = NULL;
2577 R_PurgeTexture(s->nmap );s->nmap = NULL;
2578 R_PurgeTexture(s->gloss );s->gloss = NULL;
2579 R_PurgeTexture(s->glow );s->glow = NULL;
2580 R_PurgeTexture(s->fog );s->fog = NULL;
2581 s->loadsequence = 0;
2587 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2589 char basename[MAX_QPATH];
2591 Image_StripImageExtension(name, basename, sizeof(basename));
2593 if( last == NULL ) {
2595 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2596 item = r_skinframe.hash[hashindex];
2601 // linearly search through the hash bucket
2602 for( ; item ; item = item->next ) {
2603 if( !strcmp( item->basename, basename ) ) {
2610 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2614 char basename[MAX_QPATH];
2616 Image_StripImageExtension(name, basename, sizeof(basename));
2618 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2619 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2620 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2624 rtexture_t *dyntexture;
2625 // check whether its a dynamic texture
2626 dyntexture = CL_GetDynTexture( basename );
2627 if (!add && !dyntexture)
2629 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2630 memset(item, 0, sizeof(*item));
2631 strlcpy(item->basename, basename, sizeof(item->basename));
2632 item->base = dyntexture; // either NULL or dyntexture handle
2633 item->textureflags = textureflags;
2634 item->comparewidth = comparewidth;
2635 item->compareheight = compareheight;
2636 item->comparecrc = comparecrc;
2637 item->next = r_skinframe.hash[hashindex];
2638 r_skinframe.hash[hashindex] = item;
2640 else if( item->base == NULL )
2642 rtexture_t *dyntexture;
2643 // check whether its a dynamic texture
2644 // 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]
2645 dyntexture = CL_GetDynTexture( basename );
2646 item->base = dyntexture; // either NULL or dyntexture handle
2649 R_SkinFrame_MarkUsed(item);
2653 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2655 unsigned long long avgcolor[5], wsum; \
2663 for(pix = 0; pix < cnt; ++pix) \
2666 for(comp = 0; comp < 3; ++comp) \
2668 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2671 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2673 for(comp = 0; comp < 3; ++comp) \
2674 avgcolor[comp] += getpixel * w; \
2677 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2678 avgcolor[4] += getpixel; \
2680 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2682 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2683 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2684 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2685 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2688 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2691 unsigned char *pixels;
2692 unsigned char *bumppixels;
2693 unsigned char *basepixels = NULL;
2694 int basepixels_width;
2695 int basepixels_height;
2696 skinframe_t *skinframe;
2698 if (cls.state == ca_dedicated)
2701 // return an existing skinframe if already loaded
2702 // if loading of the first image fails, don't make a new skinframe as it
2703 // would cause all future lookups of this to be missing
2704 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2705 if (skinframe && skinframe->base)
2708 basepixels = loadimagepixelsbgra(name, complain, true);
2709 if (basepixels == NULL)
2712 if (developer_loading.integer)
2713 Con_Printf("loading skin \"%s\"\n", name);
2715 // we've got some pixels to store, so really allocate this new texture now
2717 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2718 skinframe->stain = NULL;
2719 skinframe->merged = NULL;
2720 skinframe->base = r_texture_notexture;
2721 skinframe->pants = NULL;
2722 skinframe->shirt = NULL;
2723 skinframe->nmap = r_texture_blanknormalmap;
2724 skinframe->gloss = NULL;
2725 skinframe->glow = NULL;
2726 skinframe->fog = NULL;
2727 skinframe->hasalpha = false;
2729 basepixels_width = image_width;
2730 basepixels_height = image_height;
2731 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);
2733 if (textureflags & TEXF_ALPHA)
2735 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2737 if (basepixels[j] < 255)
2739 skinframe->hasalpha = true;
2743 if (r_loadfog && skinframe->hasalpha)
2745 // has transparent pixels
2746 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2747 for (j = 0;j < image_width * image_height * 4;j += 4)
2752 pixels[j+3] = basepixels[j+3];
2754 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);
2759 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2760 //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]);
2762 // _norm is the name used by tenebrae and has been adopted as standard
2763 if (r_loadnormalmap)
2765 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2767 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);
2771 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2773 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2774 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2775 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);
2777 Mem_Free(bumppixels);
2779 else if (r_shadow_bumpscale_basetexture.value > 0)
2781 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2782 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2783 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);
2787 // _luma is supported for tenebrae compatibility
2788 // (I think it's a very stupid name, but oh well)
2789 // _glow is the preferred name
2790 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;}
2791 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;}
2792 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;}
2793 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;}
2796 Mem_Free(basepixels);
2801 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2802 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2805 unsigned char *temp1, *temp2;
2806 skinframe_t *skinframe;
2808 if (cls.state == ca_dedicated)
2811 // if already loaded just return it, otherwise make a new skinframe
2812 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2813 if (skinframe && skinframe->base)
2816 skinframe->stain = NULL;
2817 skinframe->merged = NULL;
2818 skinframe->base = r_texture_notexture;
2819 skinframe->pants = NULL;
2820 skinframe->shirt = NULL;
2821 skinframe->nmap = r_texture_blanknormalmap;
2822 skinframe->gloss = NULL;
2823 skinframe->glow = NULL;
2824 skinframe->fog = NULL;
2825 skinframe->hasalpha = false;
2827 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2831 if (developer_loading.integer)
2832 Con_Printf("loading 32bit skin \"%s\"\n", name);
2834 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2836 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2837 temp2 = temp1 + width * height * 4;
2838 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2839 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2842 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2843 if (textureflags & TEXF_ALPHA)
2845 for (i = 3;i < width * height * 4;i += 4)
2847 if (skindata[i] < 255)
2849 skinframe->hasalpha = true;
2853 if (r_loadfog && skinframe->hasalpha)
2855 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2856 memcpy(fogpixels, skindata, width * height * 4);
2857 for (i = 0;i < width * height * 4;i += 4)
2858 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2859 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2860 Mem_Free(fogpixels);
2864 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2865 //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]);
2870 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2874 skinframe_t *skinframe;
2876 if (cls.state == ca_dedicated)
2879 // if already loaded just return it, otherwise make a new skinframe
2880 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2881 if (skinframe && skinframe->base)
2884 skinframe->stain = NULL;
2885 skinframe->merged = NULL;
2886 skinframe->base = r_texture_notexture;
2887 skinframe->pants = NULL;
2888 skinframe->shirt = NULL;
2889 skinframe->nmap = r_texture_blanknormalmap;
2890 skinframe->gloss = NULL;
2891 skinframe->glow = NULL;
2892 skinframe->fog = NULL;
2893 skinframe->hasalpha = false;
2895 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2899 if (developer_loading.integer)
2900 Con_Printf("loading quake skin \"%s\"\n", name);
2902 // 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)
2903 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
2904 memcpy(skinframe->qpixels, skindata, width*height);
2905 skinframe->qwidth = width;
2906 skinframe->qheight = height;
2909 for (i = 0;i < width * height;i++)
2910 featuresmask |= palette_featureflags[skindata[i]];
2912 skinframe->hasalpha = false;
2913 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2914 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2915 skinframe->qgeneratemerged = true;
2916 skinframe->qgeneratebase = skinframe->qhascolormapping;
2917 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2919 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2920 //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]);
2925 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2929 unsigned char *skindata;
2931 if (!skinframe->qpixels)
2934 if (!skinframe->qhascolormapping)
2935 colormapped = false;
2939 if (!skinframe->qgeneratebase)
2944 if (!skinframe->qgeneratemerged)
2948 width = skinframe->qwidth;
2949 height = skinframe->qheight;
2950 skindata = skinframe->qpixels;
2952 if (skinframe->qgeneratenmap)
2954 unsigned char *temp1, *temp2;
2955 skinframe->qgeneratenmap = false;
2956 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2957 temp2 = temp1 + width * height * 4;
2958 // use either a custom palette or the quake palette
2959 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2960 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2961 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2965 if (skinframe->qgenerateglow)
2967 skinframe->qgenerateglow = false;
2968 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
2973 skinframe->qgeneratebase = false;
2974 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);
2975 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
2976 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
2980 skinframe->qgeneratemerged = false;
2981 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
2984 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
2986 Mem_Free(skinframe->qpixels);
2987 skinframe->qpixels = NULL;
2991 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)
2994 skinframe_t *skinframe;
2996 if (cls.state == ca_dedicated)
2999 // if already loaded just return it, otherwise make a new skinframe
3000 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3001 if (skinframe && skinframe->base)
3004 skinframe->stain = NULL;
3005 skinframe->merged = NULL;
3006 skinframe->base = r_texture_notexture;
3007 skinframe->pants = NULL;
3008 skinframe->shirt = NULL;
3009 skinframe->nmap = r_texture_blanknormalmap;
3010 skinframe->gloss = NULL;
3011 skinframe->glow = NULL;
3012 skinframe->fog = NULL;
3013 skinframe->hasalpha = false;
3015 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3019 if (developer_loading.integer)
3020 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3022 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
3023 if (textureflags & TEXF_ALPHA)
3025 for (i = 0;i < width * height;i++)
3027 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3029 skinframe->hasalpha = true;
3033 if (r_loadfog && skinframe->hasalpha)
3034 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
3037 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3038 //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]);
3043 skinframe_t *R_SkinFrame_LoadMissing(void)
3045 skinframe_t *skinframe;
3047 if (cls.state == ca_dedicated)
3050 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
3051 skinframe->stain = NULL;
3052 skinframe->merged = NULL;
3053 skinframe->base = r_texture_notexture;
3054 skinframe->pants = NULL;
3055 skinframe->shirt = NULL;
3056 skinframe->nmap = r_texture_blanknormalmap;
3057 skinframe->gloss = NULL;
3058 skinframe->glow = NULL;
3059 skinframe->fog = NULL;
3060 skinframe->hasalpha = false;
3062 skinframe->avgcolor[0] = rand() / RAND_MAX;
3063 skinframe->avgcolor[1] = rand() / RAND_MAX;
3064 skinframe->avgcolor[2] = rand() / RAND_MAX;
3065 skinframe->avgcolor[3] = 1;
3070 void R_Main_FreeViewCache(void)
3072 if (r_refdef.viewcache.entityvisible)
3073 Mem_Free(r_refdef.viewcache.entityvisible);
3074 if (r_refdef.viewcache.world_pvsbits)
3075 Mem_Free(r_refdef.viewcache.world_pvsbits);
3076 if (r_refdef.viewcache.world_leafvisible)
3077 Mem_Free(r_refdef.viewcache.world_leafvisible);
3078 if (r_refdef.viewcache.world_surfacevisible)
3079 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3080 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3083 void R_Main_ResizeViewCache(void)
3085 int numentities = r_refdef.scene.numentities;
3086 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3087 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3088 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3089 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3090 if (r_refdef.viewcache.maxentities < numentities)
3092 r_refdef.viewcache.maxentities = numentities;
3093 if (r_refdef.viewcache.entityvisible)
3094 Mem_Free(r_refdef.viewcache.entityvisible);
3095 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3097 if (r_refdef.viewcache.world_numclusters != numclusters)
3099 r_refdef.viewcache.world_numclusters = numclusters;
3100 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3101 if (r_refdef.viewcache.world_pvsbits)
3102 Mem_Free(r_refdef.viewcache.world_pvsbits);
3103 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3105 if (r_refdef.viewcache.world_numleafs != numleafs)
3107 r_refdef.viewcache.world_numleafs = numleafs;
3108 if (r_refdef.viewcache.world_leafvisible)
3109 Mem_Free(r_refdef.viewcache.world_leafvisible);
3110 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3112 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3114 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3115 if (r_refdef.viewcache.world_surfacevisible)
3116 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3117 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3121 extern rtexture_t *loadingscreentexture;
3122 void gl_main_start(void)
3124 loadingscreentexture = NULL;
3125 r_texture_blanknormalmap = NULL;
3126 r_texture_white = NULL;
3127 r_texture_grey128 = NULL;
3128 r_texture_black = NULL;
3129 r_texture_whitecube = NULL;
3130 r_texture_normalizationcube = NULL;
3131 r_texture_fogattenuation = NULL;
3132 r_texture_gammaramps = NULL;
3134 switch(vid.renderpath)
3136 case RENDERPATH_GL20:
3137 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3138 Cvar_SetValueQuick(&gl_combine, 1);
3139 Cvar_SetValueQuick(&r_glsl, 1);
3140 r_loadnormalmap = true;
3144 case RENDERPATH_GL13:
3145 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3146 Cvar_SetValueQuick(&gl_combine, 1);
3147 Cvar_SetValueQuick(&r_glsl, 0);
3148 r_loadnormalmap = false;
3149 r_loadgloss = false;
3152 case RENDERPATH_GL11:
3153 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3154 Cvar_SetValueQuick(&gl_combine, 0);
3155 Cvar_SetValueQuick(&r_glsl, 0);
3156 r_loadnormalmap = false;
3157 r_loadgloss = false;
3163 R_FrameData_Reset();
3167 memset(r_queries, 0, sizeof(r_queries));
3169 r_qwskincache = NULL;
3170 r_qwskincache_size = 0;
3172 // set up r_skinframe loading system for textures
3173 memset(&r_skinframe, 0, sizeof(r_skinframe));
3174 r_skinframe.loadsequence = 1;
3175 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3177 r_main_texturepool = R_AllocTexturePool();
3178 R_BuildBlankTextures();
3180 if (vid.support.arb_texture_cube_map)
3183 R_BuildNormalizationCube();
3185 r_texture_fogattenuation = NULL;
3186 r_texture_gammaramps = NULL;
3187 //r_texture_fogintensity = NULL;
3188 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3189 memset(&r_waterstate, 0, sizeof(r_waterstate));
3190 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3191 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3192 memset(&r_svbsp, 0, sizeof (r_svbsp));
3194 r_refdef.fogmasktable_density = 0;
3197 void gl_main_shutdown(void)
3200 R_FrameData_Reset();
3202 R_Main_FreeViewCache();
3205 qglDeleteQueriesARB(r_maxqueries, r_queries);
3209 memset(r_queries, 0, sizeof(r_queries));
3211 r_qwskincache = NULL;
3212 r_qwskincache_size = 0;
3214 // clear out the r_skinframe state
3215 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3216 memset(&r_skinframe, 0, sizeof(r_skinframe));
3219 Mem_Free(r_svbsp.nodes);
3220 memset(&r_svbsp, 0, sizeof (r_svbsp));
3221 R_FreeTexturePool(&r_main_texturepool);
3222 loadingscreentexture = NULL;
3223 r_texture_blanknormalmap = NULL;
3224 r_texture_white = NULL;
3225 r_texture_grey128 = NULL;
3226 r_texture_black = NULL;
3227 r_texture_whitecube = NULL;
3228 r_texture_normalizationcube = NULL;
3229 r_texture_fogattenuation = NULL;
3230 r_texture_gammaramps = NULL;
3231 //r_texture_fogintensity = NULL;
3232 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3233 memset(&r_waterstate, 0, sizeof(r_waterstate));
3237 extern void CL_ParseEntityLump(char *entitystring);
3238 void gl_main_newmap(void)
3240 // FIXME: move this code to client
3242 char *entities, entname[MAX_QPATH];
3244 Mem_Free(r_qwskincache);
3245 r_qwskincache = NULL;
3246 r_qwskincache_size = 0;
3249 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
3250 l = (int)strlen(entname) - 4;
3251 if (l >= 0 && !strcmp(entname + l, ".bsp"))
3253 memcpy(entname + l, ".ent", 5);
3254 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3256 CL_ParseEntityLump(entities);
3261 if (cl.worldmodel->brush.entities)
3262 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3264 R_Main_FreeViewCache();
3266 R_FrameData_Reset();
3269 void GL_Main_Init(void)
3271 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3273 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3274 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3275 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3276 if (gamemode == GAME_NEHAHRA)
3278 Cvar_RegisterVariable (&gl_fogenable);
3279 Cvar_RegisterVariable (&gl_fogdensity);
3280 Cvar_RegisterVariable (&gl_fogred);
3281 Cvar_RegisterVariable (&gl_foggreen);
3282 Cvar_RegisterVariable (&gl_fogblue);
3283 Cvar_RegisterVariable (&gl_fogstart);
3284 Cvar_RegisterVariable (&gl_fogend);
3285 Cvar_RegisterVariable (&gl_skyclip);
3287 Cvar_RegisterVariable(&r_motionblur);
3288 Cvar_RegisterVariable(&r_motionblur_maxblur);
3289 Cvar_RegisterVariable(&r_motionblur_bmin);
3290 Cvar_RegisterVariable(&r_motionblur_vmin);
3291 Cvar_RegisterVariable(&r_motionblur_vmax);
3292 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3293 Cvar_RegisterVariable(&r_motionblur_randomize);
3294 Cvar_RegisterVariable(&r_damageblur);
3295 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3296 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3297 Cvar_RegisterVariable(&r_equalize_entities_by);
3298 Cvar_RegisterVariable(&r_equalize_entities_to);
3299 Cvar_RegisterVariable(&r_depthfirst);
3300 Cvar_RegisterVariable(&r_useinfinitefarclip);
3301 Cvar_RegisterVariable(&r_farclip_base);
3302 Cvar_RegisterVariable(&r_farclip_world);
3303 Cvar_RegisterVariable(&r_nearclip);
3304 Cvar_RegisterVariable(&r_showbboxes);
3305 Cvar_RegisterVariable(&r_showsurfaces);
3306 Cvar_RegisterVariable(&r_showtris);
3307 Cvar_RegisterVariable(&r_shownormals);
3308 Cvar_RegisterVariable(&r_showlighting);
3309 Cvar_RegisterVariable(&r_showshadowvolumes);
3310 Cvar_RegisterVariable(&r_showcollisionbrushes);
3311 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3312 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3313 Cvar_RegisterVariable(&r_showdisabledepthtest);
3314 Cvar_RegisterVariable(&r_drawportals);
3315 Cvar_RegisterVariable(&r_drawentities);
3316 Cvar_RegisterVariable(&r_cullentities_trace);
3317 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3318 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3319 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3320 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3321 Cvar_RegisterVariable(&r_drawviewmodel);
3322 Cvar_RegisterVariable(&r_speeds);
3323 Cvar_RegisterVariable(&r_fullbrights);
3324 Cvar_RegisterVariable(&r_wateralpha);
3325 Cvar_RegisterVariable(&r_dynamic);
3326 Cvar_RegisterVariable(&r_fullbright);
3327 Cvar_RegisterVariable(&r_shadows);
3328 Cvar_RegisterVariable(&r_shadows_darken);
3329 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3330 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3331 Cvar_RegisterVariable(&r_shadows_throwdistance);
3332 Cvar_RegisterVariable(&r_shadows_throwdirection);
3333 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3334 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3335 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3336 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3337 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3338 Cvar_RegisterVariable(&r_fog_exp2);
3339 Cvar_RegisterVariable(&r_drawfog);
3340 Cvar_RegisterVariable(&r_textureunits);
3341 Cvar_RegisterVariable(&gl_combine);
3342 Cvar_RegisterVariable(&r_glsl);
3343 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3344 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3345 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3346 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3347 Cvar_RegisterVariable(&r_glsl_postprocess);
3348 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3349 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3350 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3351 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3352 Cvar_RegisterVariable(&r_water);
3353 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3354 Cvar_RegisterVariable(&r_water_clippingplanebias);
3355 Cvar_RegisterVariable(&r_water_refractdistort);
3356 Cvar_RegisterVariable(&r_water_reflectdistort);
3357 Cvar_RegisterVariable(&r_lerpsprites);
3358 Cvar_RegisterVariable(&r_lerpmodels);
3359 Cvar_RegisterVariable(&r_lerplightstyles);
3360 Cvar_RegisterVariable(&r_waterscroll);
3361 Cvar_RegisterVariable(&r_bloom);
3362 Cvar_RegisterVariable(&r_bloom_colorscale);
3363 Cvar_RegisterVariable(&r_bloom_brighten);
3364 Cvar_RegisterVariable(&r_bloom_blur);
3365 Cvar_RegisterVariable(&r_bloom_resolution);
3366 Cvar_RegisterVariable(&r_bloom_colorexponent);
3367 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3368 Cvar_RegisterVariable(&r_hdr);
3369 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3370 Cvar_RegisterVariable(&r_hdr_glowintensity);
3371 Cvar_RegisterVariable(&r_hdr_range);
3372 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3373 Cvar_RegisterVariable(&developer_texturelogging);
3374 Cvar_RegisterVariable(&gl_lightmaps);
3375 Cvar_RegisterVariable(&r_test);
3376 Cvar_RegisterVariable(&r_batchmode);
3377 Cvar_RegisterVariable(&r_glsl_saturation);
3378 Cvar_RegisterVariable(&r_framedatasize);
3379 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3380 Cvar_SetValue("r_fullbrights", 0);
3381 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3383 Cvar_RegisterVariable(&r_track_sprites);
3384 Cvar_RegisterVariable(&r_track_sprites_flags);
3385 Cvar_RegisterVariable(&r_track_sprites_scalew);
3386 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3389 extern void R_Textures_Init(void);
3390 extern void GL_Draw_Init(void);
3391 extern void GL_Main_Init(void);
3392 extern void R_Shadow_Init(void);
3393 extern void R_Sky_Init(void);
3394 extern void GL_Surf_Init(void);
3395 extern void R_Particles_Init(void);
3396 extern void R_Explosion_Init(void);
3397 extern void gl_backend_init(void);
3398 extern void Sbar_Init(void);
3399 extern void R_LightningBeams_Init(void);
3400 extern void Mod_RenderInit(void);
3402 void Render_Init(void)
3414 R_LightningBeams_Init();
3423 extern char *ENGINE_EXTENSIONS;
3426 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3427 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3428 gl_version = (const char *)qglGetString(GL_VERSION);
3429 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3433 if (!gl_platformextensions)
3434 gl_platformextensions = "";
3436 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3437 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3438 Con_Printf("GL_VERSION: %s\n", gl_version);
3439 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3440 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3442 VID_CheckExtensions();
3444 // LordHavoc: report supported extensions
3445 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3447 // clear to black (loading plaque will be seen over this)
3449 qglClearColor(0,0,0,1);CHECKGLERROR
3450 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3453 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3457 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3459 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3462 p = r_refdef.view.frustum + i;
3467 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3471 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3475 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3479 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3483 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3487 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3491 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3495 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3503 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3507 for (i = 0;i < numplanes;i++)
3514 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3518 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3522 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3526 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3530 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3534 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3538 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3542 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3550 //==================================================================================
3552 // LordHavoc: this stores temporary data used within the same frame
3554 qboolean r_framedata_failed;
3555 static size_t r_framedata_size;
3556 static size_t r_framedata_current;
3557 static void *r_framedata_base;
3559 void R_FrameData_Reset(void)
3561 if (r_framedata_base);
3562 Mem_Free(r_framedata_base);
3563 r_framedata_base = NULL;
3564 r_framedata_size = 0;
3565 r_framedata_current = 0;
3566 r_framedata_failed = false;
3569 void R_FrameData_NewFrame(void)
3572 if (r_framedata_failed)
3573 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
3574 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
3575 wantedsize = bound(65536, wantedsize, 128*1024*1024);
3576 if (r_framedata_size != wantedsize)
3578 r_framedata_size = wantedsize;
3579 if (r_framedata_base);
3580 Mem_Free(r_framedata_base);
3581 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
3583 r_framedata_current = 0;
3584 r_framedata_failed = false;
3587 void *R_FrameData_Alloc(size_t size)
3591 // align to 16 byte boundary
3592 size = (size + 15) & ~15;
3593 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
3594 r_framedata_current += size;
3597 if (r_framedata_current > r_framedata_size)
3598 r_framedata_failed = true;
3600 // return NULL on everything after a failure
3601 if (r_framedata_failed)
3607 void *R_FrameData_Store(size_t size, void *data)
3609 void *d = R_FrameData_Alloc(size);
3611 memcpy(d, data, size);
3615 //==================================================================================
3617 // LordHavoc: animcache originally written by Echon, rewritten since then
3620 * Animation cache prevents re-generating mesh data for an animated model
3621 * multiple times in one frame for lighting, shadowing, reflections, etc.
3624 void R_AnimCache_Free(void)
3628 void R_AnimCache_ClearCache(void)
3631 entity_render_t *ent;
3633 for (i = 0;i < r_refdef.scene.numentities;i++)
3635 ent = r_refdef.scene.entities[i];
3636 ent->animcache_vertex3f = NULL;
3637 ent->animcache_normal3f = NULL;
3638 ent->animcache_svector3f = NULL;
3639 ent->animcache_tvector3f = NULL;
3643 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3645 dp_model_t *model = ent->model;
3647 // see if it's already cached this frame
3648 if (ent->animcache_vertex3f)
3650 // add normals/tangents if needed
3651 if (wantnormals || wanttangents)
3653 if (ent->animcache_normal3f)
3654 wantnormals = false;
3655 if (ent->animcache_svector3f)
3656 wanttangents = false;
3657 if (wantnormals || wanttangents)
3659 numvertices = model->surfmesh.num_vertices;
3661 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3664 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3665 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3667 if (!r_framedata_failed)
3668 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
3674 // see if this ent is worth caching
3675 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
3677 // get some memory for this entity and generate mesh data
3678 numvertices = model->surfmesh.num_vertices;
3679 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3681 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3684 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3685 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3687 if (!r_framedata_failed)
3688 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
3690 return !r_framedata_failed;
3693 void R_AnimCache_CacheVisibleEntities(void)
3696 qboolean wantnormals = !r_showsurfaces.integer;
3697 qboolean wanttangents = !r_showsurfaces.integer;
3699 switch(vid.renderpath)
3701 case RENDERPATH_GL20:
3703 case RENDERPATH_GL13:
3704 case RENDERPATH_GL11:
3705 wanttangents = false;
3709 // TODO: thread this
3710 // NOTE: R_PrepareRTLights() also caches entities
3712 for (i = 0;i < r_refdef.scene.numentities;i++)
3713 if (r_refdef.viewcache.entityvisible[i])
3714 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3716 if (r_shadows.integer)
3717 for (i = 0;i < r_refdef.scene.numentities;i++)
3718 if (!r_refdef.viewcache.entityvisible[i])
3719 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
3722 //==================================================================================
3724 static void R_View_UpdateEntityLighting (void)
3727 entity_render_t *ent;
3728 vec3_t tempdiffusenormal, avg;
3729 vec_t f, fa, fd, fdd;
3731 for (i = 0;i < r_refdef.scene.numentities;i++)
3733 ent = r_refdef.scene.entities[i];
3735 // skip unseen models
3736 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3740 if (ent->model && ent->model->brush.num_leafs)
3742 // TODO: use modellight for r_ambient settings on world?
3743 VectorSet(ent->modellight_ambient, 0, 0, 0);
3744 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3745 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3749 // fetch the lighting from the worldmodel data
3750 VectorClear(ent->modellight_ambient);
3751 VectorClear(ent->modellight_diffuse);
3752 VectorClear(tempdiffusenormal);
3753 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3756 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3757 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3758 if(ent->flags & RENDER_EQUALIZE)
3760 // first fix up ambient lighting...
3761 if(r_equalize_entities_minambient.value > 0)
3763 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3766 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3767 if(fa < r_equalize_entities_minambient.value * fd)
3770 // fa'/fd' = minambient
3771 // fa'+0.25*fd' = fa+0.25*fd
3773 // fa' = fd' * minambient
3774 // fd'*(0.25+minambient) = fa+0.25*fd
3776 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3777 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3779 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3780 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
3781 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3782 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3787 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3789 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3790 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3793 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3794 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3795 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3801 VectorSet(ent->modellight_ambient, 1, 1, 1);
3803 // move the light direction into modelspace coordinates for lighting code
3804 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3805 if(VectorLength2(ent->modellight_lightdir) == 0)
3806 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3807 VectorNormalize(ent->modellight_lightdir);
3811 #define MAX_LINEOFSIGHTTRACES 64
3813 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3816 vec3_t boxmins, boxmaxs;
3819 dp_model_t *model = r_refdef.scene.worldmodel;
3821 if (!model || !model->brush.TraceLineOfSight)
3824 // expand the box a little
3825 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3826 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3827 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3828 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3829 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3830 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3833 VectorCopy(eye, start);
3834 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3835 if (model->brush.TraceLineOfSight(model, start, end))
3838 // try various random positions
3839 for (i = 0;i < numsamples;i++)
3841 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3842 if (model->brush.TraceLineOfSight(model, start, end))
3850 static void R_View_UpdateEntityVisible (void)
3855 entity_render_t *ent;
3857 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3858 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3860 // worldmodel can check visibility
3861 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3862 for (i = 0;i < r_refdef.scene.numentities;i++)
3864 ent = r_refdef.scene.entities[i];
3865 if (!(ent->flags & renderimask))
3866 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)))
3867 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))
3868 r_refdef.viewcache.entityvisible[i] = true;
3870 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3872 for (i = 0;i < r_refdef.scene.numentities;i++)
3874 ent = r_refdef.scene.entities[i];
3875 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3877 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3879 continue; // temp entities do pvs only
3880 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3881 ent->last_trace_visibility = realtime;
3882 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3883 r_refdef.viewcache.entityvisible[i] = 0;
3890 // no worldmodel or it can't check visibility
3891 for (i = 0;i < r_refdef.scene.numentities;i++)
3893 ent = r_refdef.scene.entities[i];
3894 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));
3899 /// only used if skyrendermasked, and normally returns false
3900 int R_DrawBrushModelsSky (void)
3903 entity_render_t *ent;
3906 for (i = 0;i < r_refdef.scene.numentities;i++)
3908 if (!r_refdef.viewcache.entityvisible[i])
3910 ent = r_refdef.scene.entities[i];
3911 if (!ent->model || !ent->model->DrawSky)
3913 ent->model->DrawSky(ent);
3919 static void R_DrawNoModel(entity_render_t *ent);
3920 static void R_DrawModels(void)
3923 entity_render_t *ent;
3925 for (i = 0;i < r_refdef.scene.numentities;i++)
3927 if (!r_refdef.viewcache.entityvisible[i])
3929 ent = r_refdef.scene.entities[i];
3930 r_refdef.stats.entities++;
3931 if (ent->model && ent->model->Draw != NULL)
3932 ent->model->Draw(ent);
3938 static void R_DrawModelsDepth(void)
3941 entity_render_t *ent;
3943 for (i = 0;i < r_refdef.scene.numentities;i++)
3945 if (!r_refdef.viewcache.entityvisible[i])
3947 ent = r_refdef.scene.entities[i];
3948 if (ent->model && ent->model->DrawDepth != NULL)
3949 ent->model->DrawDepth(ent);
3953 static void R_DrawModelsDebug(void)
3956 entity_render_t *ent;
3958 for (i = 0;i < r_refdef.scene.numentities;i++)
3960 if (!r_refdef.viewcache.entityvisible[i])
3962 ent = r_refdef.scene.entities[i];
3963 if (ent->model && ent->model->DrawDebug != NULL)
3964 ent->model->DrawDebug(ent);
3968 static void R_DrawModelsAddWaterPlanes(void)
3971 entity_render_t *ent;
3973 for (i = 0;i < r_refdef.scene.numentities;i++)
3975 if (!r_refdef.viewcache.entityvisible[i])
3977 ent = r_refdef.scene.entities[i];
3978 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3979 ent->model->DrawAddWaterPlanes(ent);
3983 static void R_View_SetFrustum(void)
3986 double slopex, slopey;
3987 vec3_t forward, left, up, origin;
3989 // we can't trust r_refdef.view.forward and friends in reflected scenes
3990 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3993 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3994 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3995 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3996 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3997 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3998 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3999 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4000 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4001 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4002 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4003 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4004 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4008 zNear = r_refdef.nearclip;
4009 nudge = 1.0 - 1.0 / (1<<23);
4010 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4011 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4012 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4013 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4014 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4015 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4016 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4017 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4023 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4024 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4025 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4026 r_refdef.view.frustum[0].dist = m[15] - m[12];
4028 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4029 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4030 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4031 r_refdef.view.frustum[1].dist = m[15] + m[12];
4033 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4034 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4035 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4036 r_refdef.view.frustum[2].dist = m[15] - m[13];
4038 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4039 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4040 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4041 r_refdef.view.frustum[3].dist = m[15] + m[13];
4043 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4044 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4045 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4046 r_refdef.view.frustum[4].dist = m[15] - m[14];
4048 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4049 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4050 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4051 r_refdef.view.frustum[5].dist = m[15] + m[14];
4054 if (r_refdef.view.useperspective)
4056 slopex = 1.0 / r_refdef.view.frustum_x;
4057 slopey = 1.0 / r_refdef.view.frustum_y;
4058 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
4059 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
4060 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
4061 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
4062 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4064 // Leaving those out was a mistake, those were in the old code, and they
4065 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4066 // I couldn't reproduce it after adding those normalizations. --blub
4067 VectorNormalize(r_refdef.view.frustum[0].normal);
4068 VectorNormalize(r_refdef.view.frustum[1].normal);
4069 VectorNormalize(r_refdef.view.frustum[2].normal);
4070 VectorNormalize(r_refdef.view.frustum[3].normal);
4072 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4073 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]);
4074 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]);
4075 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]);
4076 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]);
4078 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4079 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4080 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4081 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4082 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4086 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4087 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4088 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4089 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
4090 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4091 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
4092 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
4093 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
4094 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
4095 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4097 r_refdef.view.numfrustumplanes = 5;
4099 if (r_refdef.view.useclipplane)
4101 r_refdef.view.numfrustumplanes = 6;
4102 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4105 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4106 PlaneClassify(r_refdef.view.frustum + i);
4108 // LordHavoc: note to all quake engine coders, Quake had a special case
4109 // for 90 degrees which assumed a square view (wrong), so I removed it,
4110 // Quake2 has it disabled as well.
4112 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4113 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4114 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4115 //PlaneClassify(&frustum[0]);
4117 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4118 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4119 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4120 //PlaneClassify(&frustum[1]);
4122 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4123 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4124 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4125 //PlaneClassify(&frustum[2]);
4127 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4128 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4129 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4130 //PlaneClassify(&frustum[3]);
4133 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4134 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4135 //PlaneClassify(&frustum[4]);
4138 void R_View_Update(void)
4140 R_Main_ResizeViewCache();
4141 R_View_SetFrustum();
4142 R_View_WorldVisibility(r_refdef.view.useclipplane);
4143 R_View_UpdateEntityVisible();
4144 R_View_UpdateEntityLighting();
4147 void R_SetupView(qboolean allowwaterclippingplane)
4149 const double *customclipplane = NULL;
4151 if (r_refdef.view.useclipplane && allowwaterclippingplane)
4153 // LordHavoc: couldn't figure out how to make this approach the
4154 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4155 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4156 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4157 dist = r_refdef.view.clipplane.dist;
4158 plane[0] = r_refdef.view.clipplane.normal[0];
4159 plane[1] = r_refdef.view.clipplane.normal[1];
4160 plane[2] = r_refdef.view.clipplane.normal[2];
4162 customclipplane = plane;
4165 if (!r_refdef.view.useperspective)
4166 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);
4167 else if (vid.stencil && r_useinfinitefarclip.integer)
4168 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);
4170 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);
4171 R_SetViewport(&r_refdef.view.viewport);
4174 void R_ResetViewRendering2D(void)
4176 r_viewport_t viewport;
4179 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
4180 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);
4181 R_SetViewport(&viewport);
4182 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
4183 GL_Color(1, 1, 1, 1);
4184 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4185 GL_BlendFunc(GL_ONE, GL_ZERO);
4186 GL_AlphaTest(false);
4187 GL_ScissorTest(false);
4188 GL_DepthMask(false);
4189 GL_DepthRange(0, 1);
4190 GL_DepthTest(false);
4191 R_Mesh_Matrix(&identitymatrix);
4192 R_Mesh_ResetTextureState();
4193 GL_PolygonOffset(0, 0);
4194 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4195 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4196 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4197 qglStencilMask(~0);CHECKGLERROR
4198 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4199 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4200 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
4201 R_SetupGenericShader(true);
4204 void R_ResetViewRendering3D(void)
4209 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
4210 GL_Color(1, 1, 1, 1);
4211 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4212 GL_BlendFunc(GL_ONE, GL_ZERO);
4213 GL_AlphaTest(false);
4214 GL_ScissorTest(true);
4216 GL_DepthRange(0, 1);
4218 R_Mesh_Matrix(&identitymatrix);
4219 R_Mesh_ResetTextureState();
4220 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4221 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4222 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4223 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4224 qglStencilMask(~0);CHECKGLERROR
4225 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4226 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4227 GL_CullFace(r_refdef.view.cullface_back);
4228 R_SetupGenericShader(true);
4231 void R_RenderScene(void);
4232 void R_RenderWaterPlanes(void);
4234 static void R_Water_StartFrame(void)
4237 int waterwidth, waterheight, texturewidth, textureheight;
4238 r_waterstate_waterplane_t *p;
4240 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
4243 switch(vid.renderpath)
4245 case RENDERPATH_GL20:
4247 case RENDERPATH_GL13:
4248 case RENDERPATH_GL11:
4252 // set waterwidth and waterheight to the water resolution that will be
4253 // used (often less than the screen resolution for faster rendering)
4254 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
4255 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
4257 // calculate desired texture sizes
4258 // can't use water if the card does not support the texture size
4259 if (!r_water.integer || r_showsurfaces.integer)
4260 texturewidth = textureheight = waterwidth = waterheight = 0;
4261 else if (vid.support.arb_texture_non_power_of_two)
4263 texturewidth = waterwidth;
4264 textureheight = waterheight;
4268 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4269 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4272 // allocate textures as needed
4273 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4275 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4276 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4278 if (p->texture_refraction)
4279 R_FreeTexture(p->texture_refraction);
4280 p->texture_refraction = NULL;
4281 if (p->texture_reflection)
4282 R_FreeTexture(p->texture_reflection);
4283 p->texture_reflection = NULL;
4285 memset(&r_waterstate, 0, sizeof(r_waterstate));
4286 r_waterstate.texturewidth = texturewidth;
4287 r_waterstate.textureheight = textureheight;
4290 if (r_waterstate.texturewidth)
4292 r_waterstate.enabled = true;
4294 // when doing a reduced render (HDR) we want to use a smaller area
4295 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4296 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4298 // set up variables that will be used in shader setup
4299 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4300 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4301 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4302 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4305 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4306 r_waterstate.numwaterplanes = 0;
4309 void R_Water_AddWaterPlane(msurface_t *surface)
4311 int triangleindex, planeindex;
4317 r_waterstate_waterplane_t *p;
4318 texture_t *t = R_GetCurrentTexture(surface->texture);
4319 // just use the first triangle with a valid normal for any decisions
4320 VectorClear(normal);
4321 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4323 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4324 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4325 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4326 TriangleNormal(vert[0], vert[1], vert[2], normal);
4327 if (VectorLength2(normal) >= 0.001)
4331 VectorCopy(normal, plane.normal);
4332 VectorNormalize(plane.normal);
4333 plane.dist = DotProduct(vert[0], plane.normal);
4334 PlaneClassify(&plane);
4335 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4337 // skip backfaces (except if nocullface is set)
4338 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4340 VectorNegate(plane.normal, plane.normal);
4342 PlaneClassify(&plane);
4346 // find a matching plane if there is one
4347 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4348 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4350 if (planeindex >= r_waterstate.maxwaterplanes)
4351 return; // nothing we can do, out of planes
4353 // if this triangle does not fit any known plane rendered this frame, add one
4354 if (planeindex >= r_waterstate.numwaterplanes)
4356 // store the new plane
4357 r_waterstate.numwaterplanes++;
4359 // clear materialflags and pvs
4360 p->materialflags = 0;
4361 p->pvsvalid = false;
4363 // merge this surface's materialflags into the waterplane
4364 p->materialflags |= t->currentmaterialflags;
4365 // merge this surface's PVS into the waterplane
4366 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4367 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4368 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4370 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4375 static void R_Water_ProcessPlanes(void)
4377 r_refdef_view_t originalview;
4378 r_refdef_view_t myview;
4380 r_waterstate_waterplane_t *p;
4382 originalview = r_refdef.view;
4384 // make sure enough textures are allocated
4385 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4387 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4389 if (!p->texture_refraction)
4390 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);
4391 if (!p->texture_refraction)
4395 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4397 if (!p->texture_reflection)
4398 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);
4399 if (!p->texture_reflection)
4405 r_refdef.view = originalview;
4406 r_refdef.view.showdebug = false;
4407 r_refdef.view.width = r_waterstate.waterwidth;
4408 r_refdef.view.height = r_waterstate.waterheight;
4409 r_refdef.view.useclipplane = true;
4410 myview = r_refdef.view;
4411 r_waterstate.renderingscene = true;
4412 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4414 // render the normal view scene and copy into texture
4415 // (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)
4416 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4418 r_refdef.view = myview;
4419 r_refdef.view.clipplane = p->plane;
4420 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4421 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4422 PlaneClassify(&r_refdef.view.clipplane);
4424 R_ResetViewRendering3D();
4425 R_ClearScreen(r_refdef.fogenabled);
4429 // copy view into the screen texture
4430 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4431 GL_ActiveTexture(0);
4433 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
4436 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4438 r_refdef.view = myview;
4439 // render reflected scene and copy into texture
4440 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4441 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4442 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4443 r_refdef.view.clipplane = p->plane;
4444 // reverse the cullface settings for this render
4445 r_refdef.view.cullface_front = GL_FRONT;
4446 r_refdef.view.cullface_back = GL_BACK;
4447 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4449 r_refdef.view.usecustompvs = true;
4451 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4453 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4456 R_ResetViewRendering3D();
4457 R_ClearScreen(r_refdef.fogenabled);
4461 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4462 GL_ActiveTexture(0);
4464 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
4467 r_waterstate.renderingscene = false;
4468 r_refdef.view = originalview;
4469 R_ResetViewRendering3D();
4470 R_ClearScreen(r_refdef.fogenabled);
4474 r_refdef.view = originalview;
4475 r_waterstate.renderingscene = false;
4476 Cvar_SetValueQuick(&r_water, 0);
4477 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4481 void R_Bloom_StartFrame(void)
4483 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4485 switch(vid.renderpath)
4487 case RENDERPATH_GL20:
4489 case RENDERPATH_GL13:
4490 case RENDERPATH_GL11:
4494 // set bloomwidth and bloomheight to the bloom resolution that will be
4495 // used (often less than the screen resolution for faster rendering)
4496 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4497 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4498 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4499 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
4500 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
4502 // calculate desired texture sizes
4503 if (vid.support.arb_texture_non_power_of_two)
4505 screentexturewidth = r_refdef.view.width;
4506 screentextureheight = r_refdef.view.height;
4507 bloomtexturewidth = r_bloomstate.bloomwidth;
4508 bloomtextureheight = r_bloomstate.bloomheight;
4512 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4513 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4514 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4515 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4518 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))
4520 Cvar_SetValueQuick(&r_hdr, 0);
4521 Cvar_SetValueQuick(&r_bloom, 0);
4522 Cvar_SetValueQuick(&r_motionblur, 0);
4523 Cvar_SetValueQuick(&r_damageblur, 0);
4526 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)))
4527 screentexturewidth = screentextureheight = 0;
4528 if (!r_hdr.integer && !r_bloom.integer)
4529 bloomtexturewidth = bloomtextureheight = 0;
4531 // allocate textures as needed
4532 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4534 if (r_bloomstate.texture_screen)
4535 R_FreeTexture(r_bloomstate.texture_screen);
4536 r_bloomstate.texture_screen = NULL;
4537 r_bloomstate.screentexturewidth = screentexturewidth;
4538 r_bloomstate.screentextureheight = screentextureheight;
4539 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4540 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);
4542 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4544 if (r_bloomstate.texture_bloom)
4545 R_FreeTexture(r_bloomstate.texture_bloom);
4546 r_bloomstate.texture_bloom = NULL;
4547 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4548 r_bloomstate.bloomtextureheight = bloomtextureheight;
4549 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4550 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);
4553 // when doing a reduced render (HDR) we want to use a smaller area
4554 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4555 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4556 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4557 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4558 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4560 // set up a texcoord array for the full resolution screen image
4561 // (we have to keep this around to copy back during final render)
4562 r_bloomstate.screentexcoord2f[0] = 0;
4563 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4564 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4565 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4566 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4567 r_bloomstate.screentexcoord2f[5] = 0;
4568 r_bloomstate.screentexcoord2f[6] = 0;
4569 r_bloomstate.screentexcoord2f[7] = 0;
4571 // set up a texcoord array for the reduced resolution bloom image
4572 // (which will be additive blended over the screen image)
4573 r_bloomstate.bloomtexcoord2f[0] = 0;
4574 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4575 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4576 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4577 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4578 r_bloomstate.bloomtexcoord2f[5] = 0;
4579 r_bloomstate.bloomtexcoord2f[6] = 0;
4580 r_bloomstate.bloomtexcoord2f[7] = 0;
4582 if (r_hdr.integer || r_bloom.integer)
4584 r_bloomstate.enabled = true;
4585 r_bloomstate.hdr = r_hdr.integer != 0;
4588 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);
4591 void R_Bloom_CopyBloomTexture(float colorscale)
4593 r_refdef.stats.bloom++;
4595 // scale down screen texture to the bloom texture size
4597 R_SetViewport(&r_bloomstate.viewport);
4598 GL_BlendFunc(GL_ONE, GL_ZERO);
4599 GL_Color(colorscale, colorscale, colorscale, 1);
4600 // TODO: optimize with multitexture or GLSL
4601 R_SetupGenericShader(true);
4602 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4603 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4604 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4605 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4607 // we now have a bloom image in the framebuffer
4608 // copy it into the bloom image texture for later processing
4609 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4610 GL_ActiveTexture(0);
4612 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4613 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4616 void R_Bloom_CopyHDRTexture(void)
4618 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4619 GL_ActiveTexture(0);
4621 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
4622 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4625 void R_Bloom_MakeTexture(void)
4628 float xoffset, yoffset, r, brighten;
4630 r_refdef.stats.bloom++;
4632 R_ResetViewRendering2D();
4633 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4634 R_Mesh_ColorPointer(NULL, 0, 0);
4635 R_SetupGenericShader(true);
4637 // we have a bloom image in the framebuffer
4639 R_SetViewport(&r_bloomstate.viewport);
4641 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4644 r = bound(0, r_bloom_colorexponent.value / x, 1);
4645 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4646 GL_Color(r, r, r, 1);
4647 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4648 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4649 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4650 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4652 // copy the vertically blurred bloom view to a texture
4653 GL_ActiveTexture(0);
4655 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4656 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4659 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4660 brighten = r_bloom_brighten.value;
4662 brighten *= r_hdr_range.value;
4663 brighten = sqrt(brighten);
4665 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4666 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4667 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4669 for (dir = 0;dir < 2;dir++)
4671 // blend on at multiple vertical offsets to achieve a vertical blur
4672 // TODO: do offset blends using GLSL
4673 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4674 GL_BlendFunc(GL_ONE, GL_ZERO);
4675 for (x = -range;x <= range;x++)
4677 if (!dir){xoffset = 0;yoffset = x;}
4678 else {xoffset = x;yoffset = 0;}
4679 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4680 yoffset /= (float)r_bloomstate.bloomtextureheight;
4681 // compute a texcoord array with the specified x and y offset
4682 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4683 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4684 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4685 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4686 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4687 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4688 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4689 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4690 // this r value looks like a 'dot' particle, fading sharply to
4691 // black at the edges
4692 // (probably not realistic but looks good enough)
4693 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4694 //r = brighten/(range*2+1);
4695 r = brighten / (range * 2 + 1);
4697 r *= (1 - x*x/(float)(range*range));
4698 GL_Color(r, r, r, 1);
4699 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4700 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4701 GL_BlendFunc(GL_ONE, GL_ONE);
4704 // copy the vertically blurred bloom view to a texture
4705 GL_ActiveTexture(0);
4707 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4708 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4711 // apply subtract last
4712 // (just like it would be in a GLSL shader)
4713 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
4715 GL_BlendFunc(GL_ONE, GL_ZERO);
4716 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4717 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4718 GL_Color(1, 1, 1, 1);
4719 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4720 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4722 GL_BlendFunc(GL_ONE, GL_ONE);
4723 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4724 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4725 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4726 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4727 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4728 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4729 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4731 // copy the darkened bloom view to a texture
4732 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4733 GL_ActiveTexture(0);
4735 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4736 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4740 void R_HDR_RenderBloomTexture(void)
4742 int oldwidth, oldheight;
4743 float oldcolorscale;
4745 oldcolorscale = r_refdef.view.colorscale;
4746 oldwidth = r_refdef.view.width;
4747 oldheight = r_refdef.view.height;
4748 r_refdef.view.width = r_bloomstate.bloomwidth;
4749 r_refdef.view.height = r_bloomstate.bloomheight;
4751 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4752 // TODO: add exposure compensation features
4753 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4755 r_refdef.view.showdebug = false;
4756 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4758 R_ResetViewRendering3D();
4760 R_ClearScreen(r_refdef.fogenabled);
4761 if (r_timereport_active)
4762 R_TimeReport("HDRclear");
4765 if (r_timereport_active)
4766 R_TimeReport("visibility");
4768 // only do secondary renders with HDR if r_hdr is 2 or higher
4769 r_waterstate.numwaterplanes = 0;
4770 if (r_waterstate.enabled && r_hdr.integer >= 2)
4771 R_RenderWaterPlanes();
4773 r_refdef.view.showdebug = true;
4775 r_waterstate.numwaterplanes = 0;
4777 R_ResetViewRendering2D();
4779 R_Bloom_CopyHDRTexture();
4780 R_Bloom_MakeTexture();
4782 // restore the view settings
4783 r_refdef.view.width = oldwidth;
4784 r_refdef.view.height = oldheight;
4785 r_refdef.view.colorscale = oldcolorscale;
4787 R_ResetViewRendering3D();
4789 R_ClearScreen(r_refdef.fogenabled);
4790 if (r_timereport_active)
4791 R_TimeReport("viewclear");
4794 static void R_BlendView(void)
4796 unsigned int permutation;
4798 switch (vid.renderpath)
4800 case RENDERPATH_GL20:
4802 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4803 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4804 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4805 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4806 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4808 if (r_bloomstate.texture_screen)
4810 // make sure the buffer is available
4811 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4813 R_ResetViewRendering2D();
4814 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4815 R_Mesh_ColorPointer(NULL, 0, 0);
4816 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4817 GL_ActiveTexture(0);CHECKGLERROR
4819 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4821 // declare variables
4823 static float avgspeed;
4825 speed = VectorLength(cl.movement_velocity);
4827 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4828 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4830 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4831 speed = bound(0, speed, 1);
4832 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4834 // calculate values into a standard alpha
4835 cl.motionbluralpha = 1 - exp(-
4837 (r_motionblur.value * speed / 80)
4839 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4842 max(0.0001, cl.time - cl.oldtime) // fps independent
4845 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4846 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4848 if (cl.motionbluralpha > 0)
4850 R_SetupGenericShader(true);
4851 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4852 GL_Color(1, 1, 1, cl.motionbluralpha);
4853 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4854 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4855 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4856 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4860 // copy view into the screen texture
4861 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
4862 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4864 else if (!r_bloomstate.texture_bloom)
4866 // we may still have to do view tint...
4867 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4869 // apply a color tint to the whole view
4870 R_ResetViewRendering2D();
4871 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4872 R_Mesh_ColorPointer(NULL, 0, 0);
4873 R_SetupGenericShader(false);
4874 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4875 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4876 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4878 break; // no screen processing, no bloom, skip it
4881 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4883 // render simple bloom effect
4884 // copy the screen and shrink it and darken it for the bloom process
4885 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4886 // make the bloom texture
4887 R_Bloom_MakeTexture();
4890 R_ResetViewRendering2D();
4891 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4892 R_Mesh_ColorPointer(NULL, 0, 0);
4893 GL_Color(1, 1, 1, 1);
4894 GL_BlendFunc(GL_ONE, GL_ZERO);
4895 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4896 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4897 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4898 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4899 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4900 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4901 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4902 if (r_glsl_permutation->loc_ViewTintColor >= 0)
4903 qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4904 if (r_glsl_permutation->loc_ClientTime >= 0)
4905 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4906 if (r_glsl_permutation->loc_PixelSize >= 0)
4907 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4908 if (r_glsl_permutation->loc_UserVec1 >= 0)
4910 float a=0, b=0, c=0, d=0;
4911 #if _MSC_VER >= 1400
4912 #define sscanf sscanf_s
4914 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4915 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4917 if (r_glsl_permutation->loc_UserVec2 >= 0)
4919 float a=0, b=0, c=0, d=0;
4920 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4921 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4923 if (r_glsl_permutation->loc_UserVec3 >= 0)
4925 float a=0, b=0, c=0, d=0;
4926 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4927 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4929 if (r_glsl_permutation->loc_UserVec4 >= 0)
4931 float a=0, b=0, c=0, d=0;
4932 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4933 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4935 if (r_glsl_permutation->loc_Saturation >= 0)
4936 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4937 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4938 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4940 case RENDERPATH_GL13:
4941 case RENDERPATH_GL11:
4942 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4944 // apply a color tint to the whole view
4945 R_ResetViewRendering2D();
4946 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4947 R_Mesh_ColorPointer(NULL, 0, 0);
4948 R_SetupGenericShader(false);
4949 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4950 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4951 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4957 matrix4x4_t r_waterscrollmatrix;
4959 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4961 if (r_refdef.fog_density)
4963 r_refdef.fogcolor[0] = r_refdef.fog_red;
4964 r_refdef.fogcolor[1] = r_refdef.fog_green;
4965 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4967 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4968 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4969 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4970 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4974 VectorCopy(r_refdef.fogcolor, fogvec);
4975 // color.rgb *= ContrastBoost * SceneBrightness;
4976 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4977 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4978 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4979 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4984 void R_UpdateVariables(void)
4988 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
4990 r_refdef.farclip = r_farclip_base.value;
4991 if (r_refdef.scene.worldmodel)
4992 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
4993 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4995 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4996 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4997 r_refdef.polygonfactor = 0;
4998 r_refdef.polygonoffset = 0;
4999 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5000 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5002 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5003 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5004 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
5005 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5006 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5007 if (r_showsurfaces.integer)
5009 r_refdef.scene.rtworld = false;
5010 r_refdef.scene.rtworldshadows = false;
5011 r_refdef.scene.rtdlight = false;
5012 r_refdef.scene.rtdlightshadows = false;
5013 r_refdef.lightmapintensity = 0;
5016 if (gamemode == GAME_NEHAHRA)
5018 if (gl_fogenable.integer)
5020 r_refdef.oldgl_fogenable = true;
5021 r_refdef.fog_density = gl_fogdensity.value;
5022 r_refdef.fog_red = gl_fogred.value;
5023 r_refdef.fog_green = gl_foggreen.value;
5024 r_refdef.fog_blue = gl_fogblue.value;
5025 r_refdef.fog_alpha = 1;
5026 r_refdef.fog_start = 0;
5027 r_refdef.fog_end = gl_skyclip.value;
5028 r_refdef.fog_height = 1<<30;
5029 r_refdef.fog_fadedepth = 128;
5031 else if (r_refdef.oldgl_fogenable)
5033 r_refdef.oldgl_fogenable = false;
5034 r_refdef.fog_density = 0;
5035 r_refdef.fog_red = 0;
5036 r_refdef.fog_green = 0;
5037 r_refdef.fog_blue = 0;
5038 r_refdef.fog_alpha = 0;
5039 r_refdef.fog_start = 0;
5040 r_refdef.fog_end = 0;
5041 r_refdef.fog_height = 1<<30;
5042 r_refdef.fog_fadedepth = 128;
5046 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5047 r_refdef.fog_start = max(0, r_refdef.fog_start);
5048 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5050 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
5052 if (r_refdef.fog_density && r_drawfog.integer)
5054 r_refdef.fogenabled = true;
5055 // this is the point where the fog reaches 0.9986 alpha, which we
5056 // consider a good enough cutoff point for the texture
5057 // (0.9986 * 256 == 255.6)
5058 if (r_fog_exp2.integer)
5059 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5061 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5062 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5063 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5064 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5065 // fog color was already set
5066 // update the fog texture
5067 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)
5068 R_BuildFogTexture();
5071 r_refdef.fogenabled = false;
5073 switch(vid.renderpath)
5075 case RENDERPATH_GL20:
5076 if(v_glslgamma.integer && !vid_gammatables_trivial)
5078 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5080 // build GLSL gamma texture
5081 #define RAMPWIDTH 256
5082 unsigned short ramp[RAMPWIDTH * 3];
5083 unsigned char rampbgr[RAMPWIDTH][4];
5086 r_texture_gammaramps_serial = vid_gammatables_serial;
5088 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5089 for(i = 0; i < RAMPWIDTH; ++i)
5091 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5092 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5093 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5096 if (r_texture_gammaramps)
5098 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
5102 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);
5108 // remove GLSL gamma texture
5111 case RENDERPATH_GL13:
5112 case RENDERPATH_GL11:
5117 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5118 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5124 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5125 if( scenetype != r_currentscenetype ) {
5126 // store the old scenetype
5127 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5128 r_currentscenetype = scenetype;
5129 // move in the new scene
5130 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5139 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5141 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5142 if( scenetype == r_currentscenetype ) {
5143 return &r_refdef.scene;
5145 return &r_scenes_store[ scenetype ];
5154 void R_RenderView(void)
5156 if (r_timereport_active)
5157 R_TimeReport("start");
5158 r_frame++; // used only by R_GetCurrentTexture
5159 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5161 if (!r_drawentities.integer)
5162 r_refdef.scene.numentities = 0;
5164 R_AnimCache_ClearCache();
5165 R_FrameData_NewFrame();
5167 if (r_refdef.view.isoverlay)
5169 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5170 GL_Clear( GL_DEPTH_BUFFER_BIT );
5171 R_TimeReport("depthclear");
5173 r_refdef.view.showdebug = false;
5175 r_waterstate.enabled = false;
5176 r_waterstate.numwaterplanes = 0;
5184 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
5185 return; //Host_Error ("R_RenderView: NULL worldmodel");
5187 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
5189 // break apart the view matrix into vectors for various purposes
5190 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5191 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5192 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5193 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5194 // make an inverted copy of the view matrix for tracking sprites
5195 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5197 R_Shadow_UpdateWorldLightSelection();
5199 R_Bloom_StartFrame();
5200 R_Water_StartFrame();
5203 if (r_timereport_active)
5204 R_TimeReport("viewsetup");
5206 R_ResetViewRendering3D();
5208 if (r_refdef.view.clear || r_refdef.fogenabled)
5210 R_ClearScreen(r_refdef.fogenabled);
5211 if (r_timereport_active)
5212 R_TimeReport("viewclear");
5214 r_refdef.view.clear = true;
5216 // this produces a bloom texture to be used in R_BlendView() later
5217 if (r_hdr.integer && r_bloomstate.bloomwidth)
5218 R_HDR_RenderBloomTexture();
5220 r_refdef.view.showdebug = true;
5223 if (r_timereport_active)
5224 R_TimeReport("visibility");
5226 r_waterstate.numwaterplanes = 0;
5227 if (r_waterstate.enabled)
5228 R_RenderWaterPlanes();
5231 r_waterstate.numwaterplanes = 0;
5234 if (r_timereport_active)
5235 R_TimeReport("blendview");
5237 GL_Scissor(0, 0, vid.width, vid.height);
5238 GL_ScissorTest(false);
5242 void R_RenderWaterPlanes(void)
5244 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5246 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5247 if (r_timereport_active)
5248 R_TimeReport("waterworld");
5251 // don't let sound skip if going slow
5252 if (r_refdef.scene.extraupdate)
5255 R_DrawModelsAddWaterPlanes();
5256 if (r_timereport_active)
5257 R_TimeReport("watermodels");
5259 if (r_waterstate.numwaterplanes)
5261 R_Water_ProcessPlanes();
5262 if (r_timereport_active)
5263 R_TimeReport("waterscenes");
5267 extern void R_DrawLightningBeams (void);
5268 extern void VM_CL_AddPolygonsToMeshQueue (void);
5269 extern void R_DrawPortals (void);
5270 extern cvar_t cl_locs_show;
5271 static void R_DrawLocs(void);
5272 static void R_DrawEntityBBoxes(void);
5273 static void R_DrawModelDecals(void);
5274 extern cvar_t cl_decals_newsystem;
5275 extern qboolean r_shadow_usingdeferredprepass;
5276 void R_RenderScene(void)
5278 r_refdef.stats.renders++;
5282 // don't let sound skip if going slow
5283 if (r_refdef.scene.extraupdate)
5286 R_MeshQueue_BeginScene();
5290 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);
5292 if (cl.csqc_vidvars.drawworld)
5294 // don't let sound skip if going slow
5295 if (r_refdef.scene.extraupdate)
5298 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5300 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5301 if (r_timereport_active)
5302 R_TimeReport("worldsky");
5305 if (R_DrawBrushModelsSky() && r_timereport_active)
5306 R_TimeReport("bmodelsky");
5308 if (skyrendermasked && skyrenderlater)
5310 // we have to force off the water clipping plane while rendering sky
5314 if (r_timereport_active)
5315 R_TimeReport("sky");
5319 R_AnimCache_CacheVisibleEntities();
5320 if (r_timereport_active)
5321 R_TimeReport("animation");
5323 R_Shadow_PrepareLights();
5324 if (r_timereport_active)
5325 R_TimeReport("preparelights");
5327 if (r_shadow_usingdeferredprepass)
5328 R_Shadow_DrawPrepass();
5330 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5332 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5333 if (r_timereport_active)
5334 R_TimeReport("worlddepth");
5336 if (r_depthfirst.integer >= 2)
5338 R_DrawModelsDepth();
5339 if (r_timereport_active)
5340 R_TimeReport("modeldepth");
5343 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5345 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5346 if (r_timereport_active)
5347 R_TimeReport("world");
5350 // don't let sound skip if going slow
5351 if (r_refdef.scene.extraupdate)
5355 if (r_timereport_active)
5356 R_TimeReport("models");
5358 // don't let sound skip if going slow
5359 if (r_refdef.scene.extraupdate)
5362 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5364 R_DrawModelShadows();
5365 R_ResetViewRendering3D();
5366 // don't let sound skip if going slow
5367 if (r_refdef.scene.extraupdate)
5371 if (!r_shadow_usingdeferredprepass)
5373 R_Shadow_DrawLights();
5374 if (r_timereport_active)
5375 R_TimeReport("rtlights");
5378 // don't let sound skip if going slow
5379 if (r_refdef.scene.extraupdate)
5382 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5384 R_DrawModelShadows();
5385 R_ResetViewRendering3D();
5386 // don't let sound skip if going slow
5387 if (r_refdef.scene.extraupdate)
5391 if (cl.csqc_vidvars.drawworld)
5393 if (cl_decals_newsystem.integer)
5395 R_DrawModelDecals();
5396 if (r_timereport_active)
5397 R_TimeReport("modeldecals");
5402 if (r_timereport_active)
5403 R_TimeReport("decals");
5407 if (r_timereport_active)
5408 R_TimeReport("particles");
5411 if (r_timereport_active)
5412 R_TimeReport("explosions");
5414 R_DrawLightningBeams();
5415 if (r_timereport_active)
5416 R_TimeReport("lightning");
5419 R_SetupGenericShader(true);
5420 VM_CL_AddPolygonsToMeshQueue();
5422 if (r_refdef.view.showdebug)
5424 if (cl_locs_show.integer)
5427 if (r_timereport_active)
5428 R_TimeReport("showlocs");
5431 if (r_drawportals.integer)
5434 if (r_timereport_active)
5435 R_TimeReport("portals");
5438 if (r_showbboxes.value > 0)
5440 R_DrawEntityBBoxes();
5441 if (r_timereport_active)
5442 R_TimeReport("bboxes");
5446 R_SetupGenericShader(true);
5447 R_MeshQueue_RenderTransparent();
5448 if (r_timereport_active)
5449 R_TimeReport("drawtrans");
5451 R_SetupGenericShader(true);
5453 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))
5455 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5456 if (r_timereport_active)
5457 R_TimeReport("worlddebug");
5458 R_DrawModelsDebug();
5459 if (r_timereport_active)
5460 R_TimeReport("modeldebug");
5463 R_SetupGenericShader(true);
5465 if (cl.csqc_vidvars.drawworld)
5467 R_Shadow_DrawCoronas();
5468 if (r_timereport_active)
5469 R_TimeReport("coronas");
5472 // don't let sound skip if going slow
5473 if (r_refdef.scene.extraupdate)
5476 R_ResetViewRendering2D();
5479 static const unsigned short bboxelements[36] =
5489 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5492 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5494 RSurf_ActiveWorldEntity();
5496 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5497 GL_DepthMask(false);
5498 GL_DepthRange(0, 1);
5499 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5500 R_Mesh_ResetTextureState();
5502 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5503 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5504 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5505 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5506 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5507 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5508 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5509 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5510 R_FillColors(color4f, 8, cr, cg, cb, ca);
5511 if (r_refdef.fogenabled)
5513 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5515 f1 = RSurf_FogVertex(v);
5517 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5518 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5519 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5522 R_Mesh_VertexPointer(vertex3f, 0, 0);
5523 R_Mesh_ColorPointer(color4f, 0, 0);
5524 R_Mesh_ResetTextureState();
5525 R_SetupGenericShader(false);
5526 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5529 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5533 prvm_edict_t *edict;
5534 prvm_prog_t *prog_save = prog;
5536 // this function draws bounding boxes of server entities
5540 GL_CullFace(GL_NONE);
5541 R_SetupGenericShader(false);
5545 for (i = 0;i < numsurfaces;i++)
5547 edict = PRVM_EDICT_NUM(surfacelist[i]);
5548 switch ((int)edict->fields.server->solid)
5550 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5551 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5552 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5553 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5554 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5555 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5557 color[3] *= r_showbboxes.value;
5558 color[3] = bound(0, color[3], 1);
5559 GL_DepthTest(!r_showdisabledepthtest.integer);
5560 GL_CullFace(r_refdef.view.cullface_front);
5561 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5567 static void R_DrawEntityBBoxes(void)
5570 prvm_edict_t *edict;
5572 prvm_prog_t *prog_save = prog;
5574 // this function draws bounding boxes of server entities
5580 for (i = 0;i < prog->num_edicts;i++)
5582 edict = PRVM_EDICT_NUM(i);
5583 if (edict->priv.server->free)
5585 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5586 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5588 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5590 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5591 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5597 static const int nomodelelement3i[24] =
5609 static const unsigned short nomodelelement3s[24] =
5621 static const float nomodelvertex3f[6*3] =
5631 static const float nomodelcolor4f[6*4] =
5633 0.0f, 0.0f, 0.5f, 1.0f,
5634 0.0f, 0.0f, 0.5f, 1.0f,
5635 0.0f, 0.5f, 0.0f, 1.0f,
5636 0.0f, 0.5f, 0.0f, 1.0f,
5637 0.5f, 0.0f, 0.0f, 1.0f,
5638 0.5f, 0.0f, 0.0f, 1.0f
5641 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5647 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);
5649 // this is only called once per entity so numsurfaces is always 1, and
5650 // surfacelist is always {0}, so this code does not handle batches
5652 if (rsurface.ent_flags & RENDER_ADDITIVE)
5654 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5655 GL_DepthMask(false);
5657 else if (rsurface.colormod[3] < 1)
5659 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5660 GL_DepthMask(false);
5664 GL_BlendFunc(GL_ONE, GL_ZERO);
5667 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5668 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5669 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5670 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5671 R_SetupGenericShader(false);
5672 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5673 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5674 R_Mesh_ColorPointer(color4f, 0, 0);
5675 for (i = 0, c = color4f;i < 6;i++, c += 4)
5677 c[0] *= rsurface.colormod[0];
5678 c[1] *= rsurface.colormod[1];
5679 c[2] *= rsurface.colormod[2];
5680 c[3] *= rsurface.colormod[3];
5682 if (r_refdef.fogenabled)
5684 for (i = 0, c = color4f;i < 6;i++, c += 4)
5686 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5688 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5689 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5690 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5693 R_Mesh_ResetTextureState();
5694 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5697 void R_DrawNoModel(entity_render_t *ent)
5700 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5701 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5702 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5704 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5707 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5709 vec3_t right1, right2, diff, normal;
5711 VectorSubtract (org2, org1, normal);
5713 // calculate 'right' vector for start
5714 VectorSubtract (r_refdef.view.origin, org1, diff);
5715 CrossProduct (normal, diff, right1);
5716 VectorNormalize (right1);
5718 // calculate 'right' vector for end
5719 VectorSubtract (r_refdef.view.origin, org2, diff);
5720 CrossProduct (normal, diff, right2);
5721 VectorNormalize (right2);
5723 vert[ 0] = org1[0] + width * right1[0];
5724 vert[ 1] = org1[1] + width * right1[1];
5725 vert[ 2] = org1[2] + width * right1[2];
5726 vert[ 3] = org1[0] - width * right1[0];
5727 vert[ 4] = org1[1] - width * right1[1];
5728 vert[ 5] = org1[2] - width * right1[2];
5729 vert[ 6] = org2[0] - width * right2[0];
5730 vert[ 7] = org2[1] - width * right2[1];
5731 vert[ 8] = org2[2] - width * right2[2];
5732 vert[ 9] = org2[0] + width * right2[0];
5733 vert[10] = org2[1] + width * right2[1];
5734 vert[11] = org2[2] + width * right2[2];
5737 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)
5739 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5740 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5741 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5742 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5743 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5744 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5745 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5746 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5747 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5748 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5749 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5750 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5753 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5758 VectorSet(v, x, y, z);
5759 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5760 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5762 if (i == mesh->numvertices)
5764 if (mesh->numvertices < mesh->maxvertices)
5766 VectorCopy(v, vertex3f);
5767 mesh->numvertices++;
5769 return mesh->numvertices;
5775 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5779 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5780 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5781 e = mesh->element3i + mesh->numtriangles * 3;
5782 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5784 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5785 if (mesh->numtriangles < mesh->maxtriangles)
5790 mesh->numtriangles++;
5792 element[1] = element[2];
5796 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5800 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5801 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5802 e = mesh->element3i + mesh->numtriangles * 3;
5803 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5805 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5806 if (mesh->numtriangles < mesh->maxtriangles)
5811 mesh->numtriangles++;
5813 element[1] = element[2];
5817 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5818 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5820 int planenum, planenum2;
5823 mplane_t *plane, *plane2;
5825 double temppoints[2][256*3];
5826 // figure out how large a bounding box we need to properly compute this brush
5828 for (w = 0;w < numplanes;w++)
5829 maxdist = max(maxdist, fabs(planes[w].dist));
5830 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5831 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5832 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5836 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5837 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5839 if (planenum2 == planenum)
5841 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);
5844 if (tempnumpoints < 3)
5846 // generate elements forming a triangle fan for this polygon
5847 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5851 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)
5853 texturelayer_t *layer;
5854 layer = t->currentlayers + t->currentnumlayers++;
5856 layer->depthmask = depthmask;
5857 layer->blendfunc1 = blendfunc1;
5858 layer->blendfunc2 = blendfunc2;
5859 layer->texture = texture;
5860 layer->texmatrix = *matrix;
5861 layer->color[0] = r;
5862 layer->color[1] = g;
5863 layer->color[2] = b;
5864 layer->color[3] = a;
5867 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5870 index = parms[2] + r_refdef.scene.time * parms[3];
5871 index -= floor(index);
5875 case Q3WAVEFUNC_NONE:
5876 case Q3WAVEFUNC_NOISE:
5877 case Q3WAVEFUNC_COUNT:
5880 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5881 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5882 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5883 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5884 case Q3WAVEFUNC_TRIANGLE:
5886 f = index - floor(index);
5897 return (float)(parms[0] + parms[1] * f);
5900 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5905 matrix4x4_t matrix, temp;
5906 switch(tcmod->tcmod)
5910 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5911 matrix = r_waterscrollmatrix;
5913 matrix = identitymatrix;
5915 case Q3TCMOD_ENTITYTRANSLATE:
5916 // this is used in Q3 to allow the gamecode to control texcoord
5917 // scrolling on the entity, which is not supported in darkplaces yet.
5918 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5920 case Q3TCMOD_ROTATE:
5921 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5922 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5923 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5926 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5928 case Q3TCMOD_SCROLL:
5929 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5931 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5932 w = (int) tcmod->parms[0];
5933 h = (int) tcmod->parms[1];
5934 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5936 idx = (int) floor(f * w * h);
5937 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5939 case Q3TCMOD_STRETCH:
5940 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5941 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5943 case Q3TCMOD_TRANSFORM:
5944 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5945 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5946 VectorSet(tcmat + 6, 0 , 0 , 1);
5947 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5948 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5950 case Q3TCMOD_TURBULENT:
5951 // this is handled in the RSurf_PrepareVertices function
5952 matrix = identitymatrix;
5956 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5959 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5961 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5962 char name[MAX_QPATH];
5963 skinframe_t *skinframe;
5964 unsigned char pixels[296*194];
5965 strlcpy(cache->name, skinname, sizeof(cache->name));
5966 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5967 if (developer_loading.integer)
5968 Con_Printf("loading %s\n", name);
5969 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5970 if (!skinframe || !skinframe->base)
5973 fs_offset_t filesize;
5975 f = FS_LoadFile(name, tempmempool, true, &filesize);
5978 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5979 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5983 cache->skinframe = skinframe;
5986 texture_t *R_GetCurrentTexture(texture_t *t)
5989 const entity_render_t *ent = rsurface.entity;
5990 dp_model_t *model = ent->model;
5991 q3shaderinfo_layer_tcmod_t *tcmod;
5993 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5994 return t->currentframe;
5995 t->update_lastrenderframe = r_frame;
5996 t->update_lastrenderentity = (void *)ent;
5998 // switch to an alternate material if this is a q1bsp animated material
6000 texture_t *texture = t;
6001 int s = rsurface.ent_skinnum;
6002 if ((unsigned int)s >= (unsigned int)model->numskins)
6004 if (model->skinscenes)
6006 if (model->skinscenes[s].framecount > 1)
6007 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6009 s = model->skinscenes[s].firstframe;
6012 t = t + s * model->num_surfaces;
6015 // use an alternate animation if the entity's frame is not 0,
6016 // and only if the texture has an alternate animation
6017 if (rsurface.ent_alttextures && t->anim_total[1])
6018 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
6020 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
6022 texture->currentframe = t;
6025 // update currentskinframe to be a qw skin or animation frame
6026 if (rsurface.ent_qwskin >= 0)
6028 i = rsurface.ent_qwskin;
6029 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6031 r_qwskincache_size = cl.maxclients;
6033 Mem_Free(r_qwskincache);
6034 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6036 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6037 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6038 t->currentskinframe = r_qwskincache[i].skinframe;
6039 if (t->currentskinframe == NULL)
6040 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6042 else if (t->numskinframes >= 2)
6043 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6044 if (t->backgroundnumskinframes >= 2)
6045 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
6047 t->currentmaterialflags = t->basematerialflags;
6048 t->currentalpha = rsurface.colormod[3];
6049 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
6050 t->currentalpha *= r_wateralpha.value;
6051 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
6052 t->currentalpha *= t->r_water_wateralpha;
6053 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
6054 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
6055 if (!(rsurface.ent_flags & RENDER_LIGHT))
6056 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
6057 else if (rsurface.modeltexcoordlightmap2f == NULL)
6059 // pick a model lighting mode
6060 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
6061 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
6063 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6065 if (rsurface.ent_flags & RENDER_ADDITIVE)
6066 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6067 else if (t->currentalpha < 1)
6068 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6069 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6070 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6071 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6072 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6073 if (t->backgroundnumskinframes)
6074 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6075 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6077 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
6078 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6081 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
6083 // there is no tcmod
6084 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6086 t->currenttexmatrix = r_waterscrollmatrix;
6087 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6089 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6091 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6092 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6095 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6096 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6097 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6098 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6100 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
6101 if (t->currentskinframe->qpixels)
6102 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6103 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6104 t->glosstexture = r_texture_black;
6105 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
6106 t->backgroundglosstexture = r_texture_black;
6107 t->specularpower = r_shadow_glossexponent.value;
6108 // TODO: store reference values for these in the texture?
6109 t->specularscale = 0;
6110 if (r_shadow_gloss.integer > 0)
6112 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6114 if (r_shadow_glossintensity.value > 0)
6116 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6117 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6118 t->specularscale = r_shadow_glossintensity.value;
6121 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6123 t->glosstexture = r_texture_white;
6124 t->backgroundglosstexture = r_texture_white;
6125 t->specularscale = r_shadow_gloss2intensity.value;
6126 t->specularpower = r_shadow_gloss2exponent.value;
6129 t->specularscale *= t->specularscalemod;
6130 t->specularpower *= t->specularpowermod;
6132 // lightmaps mode looks bad with dlights using actual texturing, so turn
6133 // off the colormap and glossmap, but leave the normalmap on as it still
6134 // accurately represents the shading involved
6135 if (gl_lightmaps.integer)
6137 t->basetexture = r_texture_grey128;
6138 t->backgroundbasetexture = NULL;
6139 t->specularscale = 0;
6140 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6143 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
6144 VectorClear(t->dlightcolor);
6145 t->currentnumlayers = 0;
6146 if (t->currentmaterialflags & MATERIALFLAG_WALL)
6149 int blendfunc1, blendfunc2;
6151 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6153 blendfunc1 = GL_SRC_ALPHA;
6154 blendfunc2 = GL_ONE;
6156 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6158 blendfunc1 = GL_SRC_ALPHA;
6159 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6161 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6163 blendfunc1 = t->customblendfunc[0];
6164 blendfunc2 = t->customblendfunc[1];
6168 blendfunc1 = GL_ONE;
6169 blendfunc2 = GL_ZERO;
6171 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
6172 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
6173 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
6174 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6176 // fullbright is not affected by r_refdef.lightmapintensity
6177 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]);
6178 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6179 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]);
6180 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6181 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]);
6185 vec3_t ambientcolor;
6187 // set the color tint used for lights affecting this surface
6188 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
6190 // q3bsp has no lightmap updates, so the lightstylevalue that
6191 // would normally be baked into the lightmap must be
6192 // applied to the color
6193 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
6194 if (model->type == mod_brushq3)
6195 colorscale *= r_refdef.scene.rtlightstylevalue[0];
6196 colorscale *= r_refdef.lightmapintensity;
6197 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
6198 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
6199 // basic lit geometry
6200 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]);
6201 // add pants/shirt if needed
6202 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6203 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]);
6204 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6205 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]);
6206 // now add ambient passes if needed
6207 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
6209 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]);
6210 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6211 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]);
6212 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6213 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]);
6216 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
6217 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
6218 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
6220 // if this is opaque use alpha blend which will darken the earlier
6223 // if this is an alpha blended material, all the earlier passes
6224 // were darkened by fog already, so we only need to add the fog
6225 // color ontop through the fog mask texture
6227 // if this is an additive blended material, all the earlier passes
6228 // were darkened by fog already, and we should not add fog color
6229 // (because the background was not darkened, there is no fog color
6230 // that was lost behind it).
6231 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]);
6235 return t->currentframe;
6238 rsurfacestate_t rsurface;
6240 void R_Mesh_ResizeArrays(int newvertices)
6243 if (rsurface.array_size >= newvertices)
6245 if (rsurface.array_modelvertex3f)
6246 Mem_Free(rsurface.array_modelvertex3f);
6247 rsurface.array_size = (newvertices + 1023) & ~1023;
6248 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
6249 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
6250 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
6251 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
6252 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
6253 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
6254 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
6255 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
6256 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
6257 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
6258 rsurface.array_color4f = base + rsurface.array_size * 27;
6259 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6262 void RSurf_ActiveWorldEntity(void)
6264 dp_model_t *model = r_refdef.scene.worldmodel;
6265 //if (rsurface.entity == r_refdef.scene.worldentity)
6267 rsurface.entity = r_refdef.scene.worldentity;
6268 rsurface.skeleton = NULL;
6269 rsurface.ent_skinnum = 0;
6270 rsurface.ent_qwskin = -1;
6271 rsurface.ent_shadertime = 0;
6272 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6273 if (rsurface.array_size < model->surfmesh.num_vertices)
6274 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6275 rsurface.matrix = identitymatrix;
6276 rsurface.inversematrix = identitymatrix;
6277 rsurface.matrixscale = 1;
6278 rsurface.inversematrixscale = 1;
6279 R_Mesh_Matrix(&identitymatrix);
6280 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6281 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6282 rsurface.fograngerecip = r_refdef.fograngerecip;
6283 rsurface.fogheightfade = r_refdef.fogheightfade;
6284 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6285 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6286 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6287 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6288 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6289 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6290 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6291 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
6292 rsurface.colormod[3] = 1;
6293 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
6294 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6295 rsurface.frameblend[0].lerp = 1;
6296 rsurface.ent_alttextures = false;
6297 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6298 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6299 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6300 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6301 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6302 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6303 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6304 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6305 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6306 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6307 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6308 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6309 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6310 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6311 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6312 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6313 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6314 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6315 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6316 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6317 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6318 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6319 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6320 rsurface.modelelement3i = model->surfmesh.data_element3i;
6321 rsurface.modelelement3s = model->surfmesh.data_element3s;
6322 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6323 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6324 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6325 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6326 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6327 rsurface.modelsurfaces = model->data_surfaces;
6328 rsurface.generatedvertex = false;
6329 rsurface.vertex3f = rsurface.modelvertex3f;
6330 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6331 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6332 rsurface.svector3f = rsurface.modelsvector3f;
6333 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6334 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6335 rsurface.tvector3f = rsurface.modeltvector3f;
6336 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6337 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6338 rsurface.normal3f = rsurface.modelnormal3f;
6339 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6340 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6341 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6344 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
6346 dp_model_t *model = ent->model;
6347 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6349 rsurface.entity = (entity_render_t *)ent;
6350 rsurface.skeleton = ent->skeleton;
6351 rsurface.ent_skinnum = ent->skinnum;
6352 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;
6353 rsurface.ent_shadertime = ent->shadertime;
6354 rsurface.ent_flags = ent->flags;
6355 if (rsurface.array_size < model->surfmesh.num_vertices)
6356 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6357 rsurface.matrix = ent->matrix;
6358 rsurface.inversematrix = ent->inversematrix;
6359 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6360 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6361 R_Mesh_Matrix(&rsurface.matrix);
6362 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6363 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6364 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6365 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6366 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6367 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6368 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6369 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6370 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6371 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6372 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6373 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
6374 rsurface.colormod[3] = ent->alpha;
6375 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
6376 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6377 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6378 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6379 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6380 if (ent->model->brush.submodel && !prepass)
6382 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6383 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6385 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6387 if (ent->animcache_vertex3f && !r_framedata_failed)
6389 rsurface.modelvertex3f = ent->animcache_vertex3f;
6390 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
6391 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
6392 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
6394 else if (wanttangents)
6396 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6397 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6398 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6399 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6400 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6402 else if (wantnormals)
6404 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6405 rsurface.modelsvector3f = NULL;
6406 rsurface.modeltvector3f = NULL;
6407 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6408 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6412 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6413 rsurface.modelsvector3f = NULL;
6414 rsurface.modeltvector3f = NULL;
6415 rsurface.modelnormal3f = NULL;
6416 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6418 rsurface.modelvertex3f_bufferobject = 0;
6419 rsurface.modelvertex3f_bufferoffset = 0;
6420 rsurface.modelsvector3f_bufferobject = 0;
6421 rsurface.modelsvector3f_bufferoffset = 0;
6422 rsurface.modeltvector3f_bufferobject = 0;
6423 rsurface.modeltvector3f_bufferoffset = 0;
6424 rsurface.modelnormal3f_bufferobject = 0;
6425 rsurface.modelnormal3f_bufferoffset = 0;
6426 rsurface.generatedvertex = true;
6430 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6431 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6432 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6433 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6434 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6435 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6436 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6437 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6438 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6439 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6440 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6441 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6442 rsurface.generatedvertex = false;
6444 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6445 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6446 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6447 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6448 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6449 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6450 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6451 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6452 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6453 rsurface.modelelement3i = model->surfmesh.data_element3i;
6454 rsurface.modelelement3s = model->surfmesh.data_element3s;
6455 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6456 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6457 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6458 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6459 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6460 rsurface.modelsurfaces = model->data_surfaces;
6461 rsurface.vertex3f = rsurface.modelvertex3f;
6462 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6463 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6464 rsurface.svector3f = rsurface.modelsvector3f;
6465 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6466 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6467 rsurface.tvector3f = rsurface.modeltvector3f;
6468 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6469 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6470 rsurface.normal3f = rsurface.modelnormal3f;
6471 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6472 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6473 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6476 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)
6478 rsurface.entity = r_refdef.scene.worldentity;
6479 rsurface.skeleton = NULL;
6480 rsurface.ent_skinnum = 0;
6481 rsurface.ent_qwskin = -1;
6482 rsurface.ent_shadertime = shadertime;
6483 rsurface.ent_flags = entflags;
6484 rsurface.modelnum_vertices = numvertices;
6485 rsurface.modelnum_triangles = numtriangles;
6486 if (rsurface.array_size < rsurface.modelnum_vertices)
6487 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6488 rsurface.matrix = *matrix;
6489 rsurface.inversematrix = *inversematrix;
6490 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6491 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6492 R_Mesh_Matrix(&rsurface.matrix);
6493 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6494 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6495 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6496 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6497 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6498 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6499 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6500 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6501 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6502 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6503 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6504 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
6505 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
6506 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6507 rsurface.frameblend[0].lerp = 1;
6508 rsurface.ent_alttextures = false;
6509 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6510 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6513 rsurface.modelvertex3f = vertex3f;
6514 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6515 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6516 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6518 else if (wantnormals)
6520 rsurface.modelvertex3f = vertex3f;
6521 rsurface.modelsvector3f = NULL;
6522 rsurface.modeltvector3f = NULL;
6523 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6527 rsurface.modelvertex3f = vertex3f;
6528 rsurface.modelsvector3f = NULL;
6529 rsurface.modeltvector3f = NULL;
6530 rsurface.modelnormal3f = NULL;
6532 rsurface.modelvertex3f_bufferobject = 0;
6533 rsurface.modelvertex3f_bufferoffset = 0;
6534 rsurface.modelsvector3f_bufferobject = 0;
6535 rsurface.modelsvector3f_bufferoffset = 0;
6536 rsurface.modeltvector3f_bufferobject = 0;
6537 rsurface.modeltvector3f_bufferoffset = 0;
6538 rsurface.modelnormal3f_bufferobject = 0;
6539 rsurface.modelnormal3f_bufferoffset = 0;
6540 rsurface.generatedvertex = true;
6541 rsurface.modellightmapcolor4f = color4f;
6542 rsurface.modellightmapcolor4f_bufferobject = 0;
6543 rsurface.modellightmapcolor4f_bufferoffset = 0;
6544 rsurface.modeltexcoordtexture2f = texcoord2f;
6545 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6546 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6547 rsurface.modeltexcoordlightmap2f = NULL;
6548 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6549 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6550 rsurface.modelelement3i = element3i;
6551 rsurface.modelelement3s = element3s;
6552 rsurface.modelelement3i_bufferobject = 0;
6553 rsurface.modelelement3s_bufferobject = 0;
6554 rsurface.modellightmapoffsets = NULL;
6555 rsurface.modelsurfaces = NULL;
6556 rsurface.vertex3f = rsurface.modelvertex3f;
6557 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6558 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6559 rsurface.svector3f = rsurface.modelsvector3f;
6560 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6561 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6562 rsurface.tvector3f = rsurface.modeltvector3f;
6563 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6564 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6565 rsurface.normal3f = rsurface.modelnormal3f;
6566 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6567 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6568 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6570 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6572 if ((wantnormals || wanttangents) && !normal3f)
6573 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6574 if (wanttangents && !svector3f)
6575 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);
6579 float RSurf_FogPoint(const float *v)
6581 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6582 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6583 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6584 float FogHeightFade = r_refdef.fogheightfade;
6586 unsigned int fogmasktableindex;
6587 if (r_refdef.fogplaneviewabove)
6588 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6590 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6591 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6592 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6595 float RSurf_FogVertex(const float *v)
6597 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6598 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6599 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6600 float FogHeightFade = rsurface.fogheightfade;
6602 unsigned int fogmasktableindex;
6603 if (r_refdef.fogplaneviewabove)
6604 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6606 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6607 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6608 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6611 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6612 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6615 int texturesurfaceindex;
6620 const float *v1, *in_tc;
6622 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6624 q3shaderinfo_deform_t *deform;
6625 // 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
6626 if (rsurface.generatedvertex)
6628 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6629 generatenormals = true;
6630 for (i = 0;i < Q3MAXDEFORMS;i++)
6632 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6634 generatetangents = true;
6635 generatenormals = true;
6637 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6638 generatenormals = true;
6640 if (generatenormals && !rsurface.modelnormal3f)
6642 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6643 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6644 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6645 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6647 if (generatetangents && !rsurface.modelsvector3f)
6649 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6650 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6651 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6652 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6653 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6654 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
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);
6658 rsurface.vertex3f = rsurface.modelvertex3f;
6659 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6660 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6661 rsurface.svector3f = rsurface.modelsvector3f;
6662 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6663 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6664 rsurface.tvector3f = rsurface.modeltvector3f;
6665 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6666 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6667 rsurface.normal3f = rsurface.modelnormal3f;
6668 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6669 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6670 // if vertices are deformed (sprite flares and things in maps, possibly
6671 // water waves, bulges and other deformations), generate them into
6672 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6673 // (may be static model data or generated data for an animated model, or
6674 // the previous deform pass)
6675 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6677 switch (deform->deform)
6680 case Q3DEFORM_PROJECTIONSHADOW:
6681 case Q3DEFORM_TEXT0:
6682 case Q3DEFORM_TEXT1:
6683 case Q3DEFORM_TEXT2:
6684 case Q3DEFORM_TEXT3:
6685 case Q3DEFORM_TEXT4:
6686 case Q3DEFORM_TEXT5:
6687 case Q3DEFORM_TEXT6:
6688 case Q3DEFORM_TEXT7:
6691 case Q3DEFORM_AUTOSPRITE:
6692 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6693 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6694 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6695 VectorNormalize(newforward);
6696 VectorNormalize(newright);
6697 VectorNormalize(newup);
6698 // make deformed versions of only the model vertices used by the specified surfaces
6699 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6701 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6702 // a single autosprite surface can contain multiple sprites...
6703 for (j = 0;j < surface->num_vertices - 3;j += 4)
6705 VectorClear(center);
6706 for (i = 0;i < 4;i++)
6707 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6708 VectorScale(center, 0.25f, center);
6709 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6710 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6711 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6712 for (i = 0;i < 4;i++)
6714 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6715 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6718 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);
6719 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);
6721 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6722 rsurface.vertex3f_bufferobject = 0;
6723 rsurface.vertex3f_bufferoffset = 0;
6724 rsurface.svector3f = rsurface.array_deformedsvector3f;
6725 rsurface.svector3f_bufferobject = 0;
6726 rsurface.svector3f_bufferoffset = 0;
6727 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6728 rsurface.tvector3f_bufferobject = 0;
6729 rsurface.tvector3f_bufferoffset = 0;
6730 rsurface.normal3f = rsurface.array_deformednormal3f;
6731 rsurface.normal3f_bufferobject = 0;
6732 rsurface.normal3f_bufferoffset = 0;
6734 case Q3DEFORM_AUTOSPRITE2:
6735 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6736 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6737 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6738 VectorNormalize(newforward);
6739 VectorNormalize(newright);
6740 VectorNormalize(newup);
6741 // make deformed versions of only the model vertices used by the specified surfaces
6742 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6744 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6745 const float *v1, *v2;
6755 memset(shortest, 0, sizeof(shortest));
6756 // a single autosprite surface can contain multiple sprites...
6757 for (j = 0;j < surface->num_vertices - 3;j += 4)
6759 VectorClear(center);
6760 for (i = 0;i < 4;i++)
6761 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6762 VectorScale(center, 0.25f, center);
6763 // find the two shortest edges, then use them to define the
6764 // axis vectors for rotating around the central axis
6765 for (i = 0;i < 6;i++)
6767 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6768 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6770 Debug_PolygonBegin(NULL, 0);
6771 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6772 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);
6773 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6776 l = VectorDistance2(v1, v2);
6777 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6779 l += (1.0f / 1024.0f);
6780 if (shortest[0].length2 > l || i == 0)
6782 shortest[1] = shortest[0];
6783 shortest[0].length2 = l;
6784 shortest[0].v1 = v1;
6785 shortest[0].v2 = v2;
6787 else if (shortest[1].length2 > l || i == 1)
6789 shortest[1].length2 = l;
6790 shortest[1].v1 = v1;
6791 shortest[1].v2 = v2;
6794 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6795 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6797 Debug_PolygonBegin(NULL, 0);
6798 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6799 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);
6800 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6803 // this calculates the right vector from the shortest edge
6804 // and the up vector from the edge midpoints
6805 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6806 VectorNormalize(right);
6807 VectorSubtract(end, start, up);
6808 VectorNormalize(up);
6809 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6810 VectorSubtract(rsurface.localvieworigin, center, forward);
6811 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6812 VectorNegate(forward, forward);
6813 VectorReflect(forward, 0, up, forward);
6814 VectorNormalize(forward);
6815 CrossProduct(up, forward, newright);
6816 VectorNormalize(newright);
6818 Debug_PolygonBegin(NULL, 0);
6819 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);
6820 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6821 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6825 Debug_PolygonBegin(NULL, 0);
6826 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6827 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6828 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6831 // rotate the quad around the up axis vector, this is made
6832 // especially easy by the fact we know the quad is flat,
6833 // so we only have to subtract the center position and
6834 // measure distance along the right vector, and then
6835 // multiply that by the newright vector and add back the
6837 // we also need to subtract the old position to undo the
6838 // displacement from the center, which we do with a
6839 // DotProduct, the subtraction/addition of center is also
6840 // optimized into DotProducts here
6841 l = DotProduct(right, center);
6842 for (i = 0;i < 4;i++)
6844 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6845 f = DotProduct(right, v1) - l;
6846 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6849 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);
6850 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);
6852 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6853 rsurface.vertex3f_bufferobject = 0;
6854 rsurface.vertex3f_bufferoffset = 0;
6855 rsurface.svector3f = rsurface.array_deformedsvector3f;
6856 rsurface.svector3f_bufferobject = 0;
6857 rsurface.svector3f_bufferoffset = 0;
6858 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6859 rsurface.tvector3f_bufferobject = 0;
6860 rsurface.tvector3f_bufferoffset = 0;
6861 rsurface.normal3f = rsurface.array_deformednormal3f;
6862 rsurface.normal3f_bufferobject = 0;
6863 rsurface.normal3f_bufferoffset = 0;
6865 case Q3DEFORM_NORMAL:
6866 // deform the normals to make reflections wavey
6867 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6869 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6870 for (j = 0;j < surface->num_vertices;j++)
6873 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6874 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6875 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6876 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6877 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6878 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6879 VectorNormalize(normal);
6881 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);
6883 rsurface.svector3f = rsurface.array_deformedsvector3f;
6884 rsurface.svector3f_bufferobject = 0;
6885 rsurface.svector3f_bufferoffset = 0;
6886 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6887 rsurface.tvector3f_bufferobject = 0;
6888 rsurface.tvector3f_bufferoffset = 0;
6889 rsurface.normal3f = rsurface.array_deformednormal3f;
6890 rsurface.normal3f_bufferobject = 0;
6891 rsurface.normal3f_bufferoffset = 0;
6894 // deform vertex array to make wavey water and flags and such
6895 waveparms[0] = deform->waveparms[0];
6896 waveparms[1] = deform->waveparms[1];
6897 waveparms[2] = deform->waveparms[2];
6898 waveparms[3] = deform->waveparms[3];
6899 // this is how a divisor of vertex influence on deformation
6900 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6901 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6902 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6904 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6905 for (j = 0;j < surface->num_vertices;j++)
6907 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6908 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6909 // if the wavefunc depends on time, evaluate it per-vertex
6912 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6913 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6915 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6918 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6919 rsurface.vertex3f_bufferobject = 0;
6920 rsurface.vertex3f_bufferoffset = 0;
6922 case Q3DEFORM_BULGE:
6923 // deform vertex array to make the surface have moving bulges
6924 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6926 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6927 for (j = 0;j < surface->num_vertices;j++)
6929 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6930 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6933 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6934 rsurface.vertex3f_bufferobject = 0;
6935 rsurface.vertex3f_bufferoffset = 0;
6938 // deform vertex array
6939 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6940 VectorScale(deform->parms, scale, waveparms);
6941 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6943 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6944 for (j = 0;j < surface->num_vertices;j++)
6945 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6947 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6948 rsurface.vertex3f_bufferobject = 0;
6949 rsurface.vertex3f_bufferoffset = 0;
6953 // generate texcoords based on the chosen texcoord source
6954 switch(rsurface.texture->tcgen.tcgen)
6957 case Q3TCGEN_TEXTURE:
6958 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6959 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6960 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6962 case Q3TCGEN_LIGHTMAP:
6963 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6964 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6965 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6967 case Q3TCGEN_VECTOR:
6968 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6970 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6971 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)
6973 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6974 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6977 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6978 rsurface.texcoordtexture2f_bufferobject = 0;
6979 rsurface.texcoordtexture2f_bufferoffset = 0;
6981 case Q3TCGEN_ENVIRONMENT:
6982 // make environment reflections using a spheremap
6983 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6985 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6986 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6987 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6988 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6989 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6991 // identical to Q3A's method, but executed in worldspace so
6992 // carried models can be shiny too
6994 float viewer[3], d, reflected[3], worldreflected[3];
6996 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6997 // VectorNormalize(viewer);
6999 d = DotProduct(normal, viewer);
7001 reflected[0] = normal[0]*2*d - viewer[0];
7002 reflected[1] = normal[1]*2*d - viewer[1];
7003 reflected[2] = normal[2]*2*d - viewer[2];
7004 // note: this is proportinal to viewer, so we can normalize later
7006 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7007 VectorNormalize(worldreflected);
7009 // note: this sphere map only uses world x and z!
7010 // so positive and negative y will LOOK THE SAME.
7011 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7012 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7015 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7016 rsurface.texcoordtexture2f_bufferobject = 0;
7017 rsurface.texcoordtexture2f_bufferoffset = 0;
7020 // the only tcmod that needs software vertex processing is turbulent, so
7021 // check for it here and apply the changes if needed
7022 // and we only support that as the first one
7023 // (handling a mixture of turbulent and other tcmods would be problematic
7024 // without punting it entirely to a software path)
7025 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7027 amplitude = rsurface.texture->tcmods[0].parms[1];
7028 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7029 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7031 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7032 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)
7034 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7035 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7038 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7039 rsurface.texcoordtexture2f_bufferobject = 0;
7040 rsurface.texcoordtexture2f_bufferoffset = 0;
7042 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
7043 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7044 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7045 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7048 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7051 const msurface_t *surface = texturesurfacelist[0];
7052 const msurface_t *surface2;
7057 // TODO: lock all array ranges before render, rather than on each surface
7058 if (texturenumsurfaces == 1)
7060 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7061 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);
7063 else if (r_batchmode.integer == 2)
7065 #define MAXBATCHTRIANGLES 4096
7066 int batchtriangles = 0;
7067 int batchelements[MAXBATCHTRIANGLES*3];
7068 for (i = 0;i < texturenumsurfaces;i = j)
7070 surface = texturesurfacelist[i];
7072 if (surface->num_triangles > MAXBATCHTRIANGLES)
7074 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);
7077 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7078 batchtriangles = surface->num_triangles;
7079 firstvertex = surface->num_firstvertex;
7080 endvertex = surface->num_firstvertex + surface->num_vertices;
7081 for (;j < texturenumsurfaces;j++)
7083 surface2 = texturesurfacelist[j];
7084 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7086 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7087 batchtriangles += surface2->num_triangles;
7088 firstvertex = min(firstvertex, surface2->num_firstvertex);
7089 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7091 surface2 = texturesurfacelist[j-1];
7092 numvertices = endvertex - firstvertex;
7093 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7096 else if (r_batchmode.integer == 1)
7098 for (i = 0;i < texturenumsurfaces;i = j)
7100 surface = texturesurfacelist[i];
7101 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7102 if (texturesurfacelist[j] != surface2)
7104 surface2 = texturesurfacelist[j-1];
7105 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7106 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7107 GL_LockArrays(surface->num_firstvertex, numvertices);
7108 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7113 for (i = 0;i < texturenumsurfaces;i++)
7115 surface = texturesurfacelist[i];
7116 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7117 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);
7122 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
7124 int i, planeindex, vertexindex;
7128 r_waterstate_waterplane_t *p, *bestp;
7129 const msurface_t *surface;
7130 if (r_waterstate.renderingscene)
7132 for (i = 0;i < texturenumsurfaces;i++)
7134 surface = texturesurfacelist[i];
7135 if (lightmaptexunit >= 0)
7136 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7137 if (deluxemaptexunit >= 0)
7138 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7139 // pick the closest matching water plane
7142 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7145 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7147 Matrix4x4_Transform(&rsurface.matrix, v, vert);
7148 d += fabs(PlaneDiff(vert, &p->plane));
7150 if (bestd > d || !bestp)
7158 if (refractiontexunit >= 0)
7159 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
7160 if (reflectiontexunit >= 0)
7161 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
7165 if (refractiontexunit >= 0)
7166 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
7167 if (reflectiontexunit >= 0)
7168 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
7170 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7171 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);
7175 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
7179 const msurface_t *surface = texturesurfacelist[0];
7180 const msurface_t *surface2;
7185 // TODO: lock all array ranges before render, rather than on each surface
7186 if (texturenumsurfaces == 1)
7188 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7189 if (deluxemaptexunit >= 0)
7190 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7191 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7192 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);
7194 else if (r_batchmode.integer == 2)
7196 #define MAXBATCHTRIANGLES 4096
7197 int batchtriangles = 0;
7198 int batchelements[MAXBATCHTRIANGLES*3];
7199 for (i = 0;i < texturenumsurfaces;i = j)
7201 surface = texturesurfacelist[i];
7202 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7203 if (deluxemaptexunit >= 0)
7204 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7206 if (surface->num_triangles > MAXBATCHTRIANGLES)
7208 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);
7211 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7212 batchtriangles = surface->num_triangles;
7213 firstvertex = surface->num_firstvertex;
7214 endvertex = surface->num_firstvertex + surface->num_vertices;
7215 for (;j < texturenumsurfaces;j++)
7217 surface2 = texturesurfacelist[j];
7218 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7220 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7221 batchtriangles += surface2->num_triangles;
7222 firstvertex = min(firstvertex, surface2->num_firstvertex);
7223 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7225 surface2 = texturesurfacelist[j-1];
7226 numvertices = endvertex - firstvertex;
7227 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7230 else if (r_batchmode.integer == 1)
7233 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
7234 for (i = 0;i < texturenumsurfaces;i = j)
7236 surface = texturesurfacelist[i];
7237 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7238 if (texturesurfacelist[j] != surface2)
7240 Con_Printf(" %i", j - i);
7243 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
7245 for (i = 0;i < texturenumsurfaces;i = j)
7247 surface = texturesurfacelist[i];
7248 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7249 if (deluxemaptexunit >= 0)
7250 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7251 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7252 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
7255 Con_Printf(" %i", j - i);
7257 surface2 = texturesurfacelist[j-1];
7258 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7259 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7260 GL_LockArrays(surface->num_firstvertex, numvertices);
7261 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7269 for (i = 0;i < texturenumsurfaces;i++)
7271 surface = texturesurfacelist[i];
7272 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7273 if (deluxemaptexunit >= 0)
7274 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7275 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7276 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);
7281 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7284 int texturesurfaceindex;
7285 if (r_showsurfaces.integer == 2)
7287 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7289 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7290 for (j = 0;j < surface->num_triangles;j++)
7292 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7293 GL_Color(f, f, f, 1);
7294 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7300 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7302 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7303 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7304 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);
7305 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7306 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);
7311 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7313 int texturesurfaceindex;
7317 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7319 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7320 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)
7328 rsurface.lightmapcolor4f = rsurface.array_color4f;
7329 rsurface.lightmapcolor4f_bufferobject = 0;
7330 rsurface.lightmapcolor4f_bufferoffset = 0;
7333 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7335 int texturesurfaceindex;
7341 if (rsurface.lightmapcolor4f)
7343 // generate color arrays for the surfaces in this list
7344 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7346 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7347 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)
7349 f = RSurf_FogVertex(v);
7359 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7361 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7362 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)
7364 f = RSurf_FogVertex(v);
7372 rsurface.lightmapcolor4f = rsurface.array_color4f;
7373 rsurface.lightmapcolor4f_bufferobject = 0;
7374 rsurface.lightmapcolor4f_bufferoffset = 0;
7377 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7379 int texturesurfaceindex;
7385 if (!rsurface.lightmapcolor4f)
7387 // generate color arrays for the surfaces in this list
7388 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7390 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7391 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)
7393 f = RSurf_FogVertex(v);
7394 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7395 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7396 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7400 rsurface.lightmapcolor4f = rsurface.array_color4f;
7401 rsurface.lightmapcolor4f_bufferobject = 0;
7402 rsurface.lightmapcolor4f_bufferoffset = 0;
7405 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7407 int texturesurfaceindex;
7411 if (!rsurface.lightmapcolor4f)
7413 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7415 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7416 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)
7424 rsurface.lightmapcolor4f = rsurface.array_color4f;
7425 rsurface.lightmapcolor4f_bufferobject = 0;
7426 rsurface.lightmapcolor4f_bufferoffset = 0;
7429 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7431 int texturesurfaceindex;
7435 if (!rsurface.lightmapcolor4f)
7437 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7439 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7440 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)
7442 c2[0] = c[0] + r_refdef.scene.ambient;
7443 c2[1] = c[1] + r_refdef.scene.ambient;
7444 c2[2] = c[2] + r_refdef.scene.ambient;
7448 rsurface.lightmapcolor4f = rsurface.array_color4f;
7449 rsurface.lightmapcolor4f_bufferobject = 0;
7450 rsurface.lightmapcolor4f_bufferoffset = 0;
7453 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7456 rsurface.lightmapcolor4f = NULL;
7457 rsurface.lightmapcolor4f_bufferobject = 0;
7458 rsurface.lightmapcolor4f_bufferoffset = 0;
7459 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7460 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7461 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7462 GL_Color(r, g, b, a);
7463 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7466 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7468 // TODO: optimize applyfog && applycolor case
7469 // just apply fog if necessary, and tint the fog color array if necessary
7470 rsurface.lightmapcolor4f = NULL;
7471 rsurface.lightmapcolor4f_bufferobject = 0;
7472 rsurface.lightmapcolor4f_bufferoffset = 0;
7473 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7474 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7475 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7476 GL_Color(r, g, b, a);
7477 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7480 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7482 int texturesurfaceindex;
7486 if (texturesurfacelist[0]->lightmapinfo)
7488 // generate color arrays for the surfaces in this list
7489 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7491 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7492 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7494 if (surface->lightmapinfo->samples)
7496 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7497 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7498 VectorScale(lm, scale, c);
7499 if (surface->lightmapinfo->styles[1] != 255)
7501 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7503 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7504 VectorMA(c, scale, lm, c);
7505 if (surface->lightmapinfo->styles[2] != 255)
7508 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7509 VectorMA(c, scale, lm, c);
7510 if (surface->lightmapinfo->styles[3] != 255)
7513 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7514 VectorMA(c, scale, lm, c);
7524 rsurface.lightmapcolor4f = rsurface.array_color4f;
7525 rsurface.lightmapcolor4f_bufferobject = 0;
7526 rsurface.lightmapcolor4f_bufferoffset = 0;
7530 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7531 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7532 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7534 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7535 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7536 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7537 GL_Color(r, g, b, a);
7538 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7541 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7543 int texturesurfaceindex;
7550 vec3_t ambientcolor;
7551 vec3_t diffusecolor;
7555 VectorCopy(rsurface.modellight_lightdir, lightdir);
7556 f = 0.5f * r_refdef.lightmapintensity;
7557 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7558 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7559 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7560 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7561 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7562 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7564 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7566 // generate color arrays for the surfaces in this list
7567 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7569 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7570 int numverts = surface->num_vertices;
7571 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7572 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7573 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7574 // q3-style directional shading
7575 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7577 if ((f = DotProduct(n, lightdir)) > 0)
7578 VectorMA(ambientcolor, f, diffusecolor, c);
7580 VectorCopy(ambientcolor, c);
7588 rsurface.lightmapcolor4f = rsurface.array_color4f;
7589 rsurface.lightmapcolor4f_bufferobject = 0;
7590 rsurface.lightmapcolor4f_bufferoffset = 0;
7591 *applycolor = false;
7595 *r = ambientcolor[0];
7596 *g = ambientcolor[1];
7597 *b = ambientcolor[2];
7598 rsurface.lightmapcolor4f = NULL;
7599 rsurface.lightmapcolor4f_bufferobject = 0;
7600 rsurface.lightmapcolor4f_bufferoffset = 0;
7604 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7606 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7607 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7608 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7609 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7610 GL_Color(r, g, b, a);
7611 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7614 void RSurf_SetupDepthAndCulling(void)
7616 // submodels are biased to avoid z-fighting with world surfaces that they
7617 // may be exactly overlapping (avoids z-fighting artifacts on certain
7618 // doors and things in Quake maps)
7619 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7620 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7621 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7622 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7625 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7627 // transparent sky would be ridiculous
7628 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7630 R_SetupGenericShader(false);
7631 skyrenderlater = true;
7632 RSurf_SetupDepthAndCulling();
7634 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7635 // skymasking on them, and Quake3 never did sky masking (unlike
7636 // software Quake and software Quake2), so disable the sky masking
7637 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7638 // and skymasking also looks very bad when noclipping outside the
7639 // level, so don't use it then either.
7640 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7642 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7643 R_Mesh_ColorPointer(NULL, 0, 0);
7644 R_Mesh_ResetTextureState();
7645 if (skyrendermasked)
7647 R_SetupDepthOrShadowShader();
7648 // depth-only (masking)
7649 GL_ColorMask(0,0,0,0);
7650 // just to make sure that braindead drivers don't draw
7651 // anything despite that colormask...
7652 GL_BlendFunc(GL_ZERO, GL_ONE);
7656 R_SetupGenericShader(false);
7658 GL_BlendFunc(GL_ONE, GL_ZERO);
7660 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7661 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7662 if (skyrendermasked)
7663 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7665 R_Mesh_ResetTextureState();
7666 GL_Color(1, 1, 1, 1);
7669 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
7670 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
7671 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
7673 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7676 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7677 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7678 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7679 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7680 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7681 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7682 if (rsurface.texture->backgroundcurrentskinframe)
7684 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7685 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7686 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7687 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7689 if (rsurface.texture->colormapping)
7691 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7692 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7694 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7695 if (r_shadow_usingdeferredprepass)
7697 R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture));
7698 R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture));
7700 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7701 R_Mesh_ColorPointer(NULL, 0, 0);
7703 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7705 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass)
7707 // render background
7708 GL_BlendFunc(GL_ONE, GL_ZERO);
7710 GL_AlphaTest(false);
7712 GL_Color(1, 1, 1, 1);
7713 R_Mesh_ColorPointer(NULL, 0, 0);
7715 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7716 if (r_glsl_permutation)
7718 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7719 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7720 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7721 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7722 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7723 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7724 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);
7726 GL_LockArrays(0, 0);
7728 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7729 GL_DepthMask(false);
7730 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7731 R_Mesh_ColorPointer(NULL, 0, 0);
7733 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7734 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7735 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7738 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
7739 if (!r_glsl_permutation)
7742 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7743 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7744 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7745 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7746 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7748 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7750 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7752 GL_BlendFunc(GL_ONE, GL_ZERO);
7754 GL_AlphaTest(false);
7758 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7759 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7760 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
7763 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7765 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7766 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);
7768 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7772 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7773 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);
7775 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7777 GL_LockArrays(0, 0);
7780 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7782 // OpenGL 1.3 path - anything not completely ancient
7783 int texturesurfaceindex;
7784 qboolean applycolor;
7788 const texturelayer_t *layer;
7789 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7791 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7794 int layertexrgbscale;
7795 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7797 if (layerindex == 0)
7801 GL_AlphaTest(false);
7802 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7805 GL_DepthMask(layer->depthmask && writedepth);
7806 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7807 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7809 layertexrgbscale = 4;
7810 VectorScale(layer->color, 0.25f, layercolor);
7812 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7814 layertexrgbscale = 2;
7815 VectorScale(layer->color, 0.5f, layercolor);
7819 layertexrgbscale = 1;
7820 VectorScale(layer->color, 1.0f, layercolor);
7822 layercolor[3] = layer->color[3];
7823 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7824 R_Mesh_ColorPointer(NULL, 0, 0);
7825 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7826 switch (layer->type)
7828 case TEXTURELAYERTYPE_LITTEXTURE:
7829 memset(&m, 0, sizeof(m));
7830 m.tex[0] = R_GetTexture(r_texture_white);
7831 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7832 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7833 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7834 m.tex[1] = R_GetTexture(layer->texture);
7835 m.texmatrix[1] = layer->texmatrix;
7836 m.texrgbscale[1] = layertexrgbscale;
7837 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7838 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7839 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7840 R_Mesh_TextureState(&m);
7841 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7842 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7843 else if (rsurface.uselightmaptexture)
7844 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7846 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7848 case TEXTURELAYERTYPE_TEXTURE:
7849 memset(&m, 0, sizeof(m));
7850 m.tex[0] = R_GetTexture(layer->texture);
7851 m.texmatrix[0] = layer->texmatrix;
7852 m.texrgbscale[0] = layertexrgbscale;
7853 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7854 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7855 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7856 R_Mesh_TextureState(&m);
7857 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7859 case TEXTURELAYERTYPE_FOG:
7860 memset(&m, 0, sizeof(m));
7861 m.texrgbscale[0] = layertexrgbscale;
7864 m.tex[0] = R_GetTexture(layer->texture);
7865 m.texmatrix[0] = layer->texmatrix;
7866 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7867 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7868 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7870 R_Mesh_TextureState(&m);
7871 // generate a color array for the fog pass
7872 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7873 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7879 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7880 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)
7882 f = 1 - RSurf_FogVertex(v);
7883 c[0] = layercolor[0];
7884 c[1] = layercolor[1];
7885 c[2] = layercolor[2];
7886 c[3] = f * layercolor[3];
7889 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7892 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7894 GL_LockArrays(0, 0);
7897 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7899 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7900 GL_AlphaTest(false);
7904 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7906 // OpenGL 1.1 - crusty old voodoo path
7907 int texturesurfaceindex;
7911 const texturelayer_t *layer;
7912 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7914 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7916 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7918 if (layerindex == 0)
7922 GL_AlphaTest(false);
7923 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7926 GL_DepthMask(layer->depthmask && writedepth);
7927 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7928 R_Mesh_ColorPointer(NULL, 0, 0);
7929 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7930 switch (layer->type)
7932 case TEXTURELAYERTYPE_LITTEXTURE:
7933 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7935 // two-pass lit texture with 2x rgbscale
7936 // first the lightmap pass
7937 memset(&m, 0, sizeof(m));
7938 m.tex[0] = R_GetTexture(r_texture_white);
7939 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7940 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7941 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7942 R_Mesh_TextureState(&m);
7943 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7944 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7945 else if (rsurface.uselightmaptexture)
7946 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7948 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7949 GL_LockArrays(0, 0);
7950 // then apply the texture to it
7951 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7952 memset(&m, 0, sizeof(m));
7953 m.tex[0] = R_GetTexture(layer->texture);
7954 m.texmatrix[0] = layer->texmatrix;
7955 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7956 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7957 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7958 R_Mesh_TextureState(&m);
7959 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);
7963 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7964 memset(&m, 0, sizeof(m));
7965 m.tex[0] = R_GetTexture(layer->texture);
7966 m.texmatrix[0] = layer->texmatrix;
7967 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7968 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7969 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7970 R_Mesh_TextureState(&m);
7971 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7972 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);
7974 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);
7977 case TEXTURELAYERTYPE_TEXTURE:
7978 // singletexture unlit texture with transparency support
7979 memset(&m, 0, sizeof(m));
7980 m.tex[0] = R_GetTexture(layer->texture);
7981 m.texmatrix[0] = layer->texmatrix;
7982 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7983 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7984 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7985 R_Mesh_TextureState(&m);
7986 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);
7988 case TEXTURELAYERTYPE_FOG:
7989 // singletexture fogging
7990 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7993 memset(&m, 0, sizeof(m));
7994 m.tex[0] = R_GetTexture(layer->texture);
7995 m.texmatrix[0] = layer->texmatrix;
7996 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7997 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7998 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7999 R_Mesh_TextureState(&m);
8002 R_Mesh_ResetTextureState();
8003 // generate a color array for the fog pass
8004 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8010 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8011 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)
8013 f = 1 - RSurf_FogVertex(v);
8014 c[0] = layer->color[0];
8015 c[1] = layer->color[1];
8016 c[2] = layer->color[2];
8017 c[3] = f * layer->color[3];
8020 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8023 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8025 GL_LockArrays(0, 0);
8028 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8030 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8031 GL_AlphaTest(false);
8035 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8039 GL_AlphaTest(false);
8040 R_Mesh_ColorPointer(NULL, 0, 0);
8041 R_Mesh_ResetTextureState();
8042 R_SetupGenericShader(false);
8044 if(rsurface.texture && rsurface.texture->currentskinframe)
8046 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8047 c[3] *= rsurface.texture->currentalpha;
8057 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
8059 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8060 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8061 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8064 // brighten it up (as texture value 127 means "unlit")
8065 c[0] *= 2 * r_refdef.view.colorscale;
8066 c[1] *= 2 * r_refdef.view.colorscale;
8067 c[2] *= 2 * r_refdef.view.colorscale;
8069 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8070 c[3] *= r_wateralpha.value;
8072 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8074 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8075 GL_DepthMask(false);
8077 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8079 GL_BlendFunc(GL_ONE, GL_ONE);
8080 GL_DepthMask(false);
8082 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8084 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8085 GL_DepthMask(false);
8087 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8089 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8090 GL_DepthMask(false);
8094 GL_BlendFunc(GL_ONE, GL_ZERO);
8095 GL_DepthMask(writedepth);
8098 rsurface.lightmapcolor4f = NULL;
8100 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8102 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8104 rsurface.lightmapcolor4f = NULL;
8105 rsurface.lightmapcolor4f_bufferobject = 0;
8106 rsurface.lightmapcolor4f_bufferoffset = 0;
8108 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8110 qboolean applycolor = true;
8113 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8115 r_refdef.lightmapintensity = 1;
8116 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8117 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8121 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8123 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8124 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8125 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8128 if(!rsurface.lightmapcolor4f)
8129 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8131 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8132 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8133 if(r_refdef.fogenabled)
8134 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8136 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8137 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8140 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8143 RSurf_SetupDepthAndCulling();
8144 if (r_showsurfaces.integer == 3 && !prepass)
8146 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8149 switch (vid.renderpath)
8151 case RENDERPATH_GL20:
8152 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8154 case RENDERPATH_GL13:
8155 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8157 case RENDERPATH_GL11:
8158 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8164 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8167 RSurf_SetupDepthAndCulling();
8168 if (r_showsurfaces.integer == 3 && !prepass)
8170 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8173 switch (vid.renderpath)
8175 case RENDERPATH_GL20:
8176 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8178 case RENDERPATH_GL13:
8179 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8181 case RENDERPATH_GL11:
8182 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8188 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8191 int texturenumsurfaces, endsurface;
8193 const msurface_t *surface;
8194 const msurface_t *texturesurfacelist[1024];
8196 // if the model is static it doesn't matter what value we give for
8197 // wantnormals and wanttangents, so this logic uses only rules applicable
8198 // to a model, knowing that they are meaningless otherwise
8199 if (ent == r_refdef.scene.worldentity)
8200 RSurf_ActiveWorldEntity();
8201 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8202 RSurf_ActiveModelEntity(ent, false, false, false);
8205 switch (vid.renderpath)
8207 case RENDERPATH_GL20:
8208 RSurf_ActiveModelEntity(ent, true, true, false);
8210 case RENDERPATH_GL13:
8211 case RENDERPATH_GL11:
8212 RSurf_ActiveModelEntity(ent, true, false, false);
8217 for (i = 0;i < numsurfaces;i = j)
8220 surface = rsurface.modelsurfaces + surfacelist[i];
8221 texture = surface->texture;
8222 rsurface.texture = R_GetCurrentTexture(texture);
8223 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8224 // scan ahead until we find a different texture
8225 endsurface = min(i + 1024, numsurfaces);
8226 texturenumsurfaces = 0;
8227 texturesurfacelist[texturenumsurfaces++] = surface;
8228 for (;j < endsurface;j++)
8230 surface = rsurface.modelsurfaces + surfacelist[j];
8231 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8233 texturesurfacelist[texturenumsurfaces++] = surface;
8235 // render the range of surfaces
8236 if (ent == r_refdef.scene.worldentity)
8237 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8239 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8241 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8242 GL_AlphaTest(false);
8245 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
8247 const entity_render_t *queueentity = r_refdef.scene.worldentity;
8251 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8253 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8255 RSurf_SetupDepthAndCulling();
8256 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8257 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8261 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8263 if (!rsurface.texture->currentnumlayers)
8265 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8267 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8269 RSurf_SetupDepthAndCulling();
8270 GL_AlphaTest(false);
8271 R_Mesh_ColorPointer(NULL, 0, 0);
8272 R_Mesh_ResetTextureState();
8273 R_SetupGenericShader(false);
8274 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8276 GL_BlendFunc(GL_ONE, GL_ZERO);
8277 GL_Color(0, 0, 0, 1);
8278 GL_DepthTest(writedepth);
8279 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8281 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8283 RSurf_SetupDepthAndCulling();
8284 GL_AlphaTest(false);
8285 R_Mesh_ColorPointer(NULL, 0, 0);
8286 R_Mesh_ResetTextureState();
8287 R_SetupGenericShader(false);
8288 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8290 GL_BlendFunc(GL_ONE, GL_ZERO);
8292 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8294 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8295 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8296 else if (!rsurface.texture->currentnumlayers)
8298 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8300 // transparent surfaces get pushed off into the transparent queue
8301 int surfacelistindex;
8302 const msurface_t *surface;
8303 vec3_t tempcenter, center;
8304 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8306 surface = texturesurfacelist[surfacelistindex];
8307 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8308 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8309 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8310 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8311 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8316 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8317 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8322 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8326 // break the surface list down into batches by texture and use of lightmapping
8327 for (i = 0;i < numsurfaces;i = j)
8330 // texture is the base texture pointer, rsurface.texture is the
8331 // current frame/skin the texture is directing us to use (for example
8332 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8333 // use skin 1 instead)
8334 texture = surfacelist[i]->texture;
8335 rsurface.texture = R_GetCurrentTexture(texture);
8336 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8337 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8339 // if this texture is not the kind we want, skip ahead to the next one
8340 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8344 // simply scan ahead until we find a different texture or lightmap state
8345 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8347 // render the range of surfaces
8348 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
8352 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
8357 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8359 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8361 RSurf_SetupDepthAndCulling();
8362 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8363 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8367 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8369 if (!rsurface.texture->currentnumlayers)
8371 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8373 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8375 RSurf_SetupDepthAndCulling();
8376 GL_AlphaTest(false);
8377 R_Mesh_ColorPointer(NULL, 0, 0);
8378 R_Mesh_ResetTextureState();
8379 R_SetupGenericShader(false);
8380 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8382 GL_BlendFunc(GL_ONE, GL_ZERO);
8383 GL_Color(0, 0, 0, 1);
8384 GL_DepthTest(writedepth);
8385 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8387 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8389 RSurf_SetupDepthAndCulling();
8390 GL_AlphaTest(false);
8391 R_Mesh_ColorPointer(NULL, 0, 0);
8392 R_Mesh_ResetTextureState();
8393 R_SetupGenericShader(false);
8394 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8396 GL_BlendFunc(GL_ONE, GL_ZERO);
8398 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8400 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8401 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8402 else if (!rsurface.texture->currentnumlayers)
8404 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8406 // transparent surfaces get pushed off into the transparent queue
8407 int surfacelistindex;
8408 const msurface_t *surface;
8409 vec3_t tempcenter, center;
8410 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8412 surface = texturesurfacelist[surfacelistindex];
8413 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8414 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8415 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8416 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8417 if (queueentity->transparent_offset) // transparent offset
8419 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8420 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8421 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8423 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8428 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8429 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8434 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8438 // break the surface list down into batches by texture and use of lightmapping
8439 for (i = 0;i < numsurfaces;i = j)
8442 // texture is the base texture pointer, rsurface.texture is the
8443 // current frame/skin the texture is directing us to use (for example
8444 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8445 // use skin 1 instead)
8446 texture = surfacelist[i]->texture;
8447 rsurface.texture = R_GetCurrentTexture(texture);
8448 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8449 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8451 // if this texture is not the kind we want, skip ahead to the next one
8452 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8456 // simply scan ahead until we find a different texture or lightmap state
8457 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8459 // render the range of surfaces
8460 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
8464 float locboxvertex3f[6*4*3] =
8466 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8467 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8468 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8469 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8470 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8471 1,0,0, 0,0,0, 0,1,0, 1,1,0
8474 unsigned short locboxelements[6*2*3] =
8484 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8487 cl_locnode_t *loc = (cl_locnode_t *)ent;
8489 float vertex3f[6*4*3];
8491 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8492 GL_DepthMask(false);
8493 GL_DepthRange(0, 1);
8494 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8496 GL_CullFace(GL_NONE);
8497 R_Mesh_Matrix(&identitymatrix);
8499 R_Mesh_VertexPointer(vertex3f, 0, 0);
8500 R_Mesh_ColorPointer(NULL, 0, 0);
8501 R_Mesh_ResetTextureState();
8502 R_SetupGenericShader(false);
8505 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8506 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8507 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8508 surfacelist[0] < 0 ? 0.5f : 0.125f);
8510 if (VectorCompare(loc->mins, loc->maxs))
8512 VectorSet(size, 2, 2, 2);
8513 VectorMA(loc->mins, -0.5f, size, mins);
8517 VectorCopy(loc->mins, mins);
8518 VectorSubtract(loc->maxs, loc->mins, size);
8521 for (i = 0;i < 6*4*3;)
8522 for (j = 0;j < 3;j++, i++)
8523 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8525 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8528 void R_DrawLocs(void)
8531 cl_locnode_t *loc, *nearestloc;
8533 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8534 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8536 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8537 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8541 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8543 if (decalsystem->decals)
8544 Mem_Free(decalsystem->decals);
8545 memset(decalsystem, 0, sizeof(*decalsystem));
8548 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)
8555 // expand or initialize the system
8556 if (decalsystem->maxdecals <= decalsystem->numdecals)
8558 decalsystem_t old = *decalsystem;
8559 qboolean useshortelements;
8560 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8561 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8562 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)));
8563 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8564 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8565 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8566 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8567 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8568 if (decalsystem->numdecals)
8569 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8571 Mem_Free(old.decals);
8572 for (i = 0;i < decalsystem->maxdecals*3;i++)
8573 decalsystem->element3i[i] = i;
8574 if (useshortelements)
8575 for (i = 0;i < decalsystem->maxdecals*3;i++)
8576 decalsystem->element3s[i] = i;
8579 // grab a decal and search for another free slot for the next one
8580 maxdecals = decalsystem->maxdecals;
8581 decals = decalsystem->decals;
8582 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8583 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8585 decalsystem->freedecal = i;
8586 if (decalsystem->numdecals <= i)
8587 decalsystem->numdecals = i + 1;
8589 // initialize the decal
8591 decal->triangleindex = triangleindex;
8592 decal->surfaceindex = surfaceindex;
8593 decal->decalsequence = decalsequence;
8594 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8595 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8596 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8597 decal->color4ub[0][3] = 255;
8598 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8599 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8600 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8601 decal->color4ub[1][3] = 255;
8602 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8603 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8604 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8605 decal->color4ub[2][3] = 255;
8606 decal->vertex3f[0][0] = v0[0];
8607 decal->vertex3f[0][1] = v0[1];
8608 decal->vertex3f[0][2] = v0[2];
8609 decal->vertex3f[1][0] = v1[0];
8610 decal->vertex3f[1][1] = v1[1];
8611 decal->vertex3f[1][2] = v1[2];
8612 decal->vertex3f[2][0] = v2[0];
8613 decal->vertex3f[2][1] = v2[1];
8614 decal->vertex3f[2][2] = v2[2];
8615 decal->texcoord2f[0][0] = t0[0];
8616 decal->texcoord2f[0][1] = t0[1];
8617 decal->texcoord2f[1][0] = t1[0];
8618 decal->texcoord2f[1][1] = t1[1];
8619 decal->texcoord2f[2][0] = t2[0];
8620 decal->texcoord2f[2][1] = t2[1];
8623 extern cvar_t cl_decals_bias;
8624 extern cvar_t cl_decals_models;
8625 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8626 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)
8628 matrix4x4_t projection;
8629 decalsystem_t *decalsystem;
8632 const float *vertex3f;
8633 const msurface_t *surface;
8634 const msurface_t *surfaces;
8635 const int *surfacelist;
8636 const texture_t *texture;
8640 int surfacelistindex;
8643 int decalsurfaceindex;
8648 float localorigin[3];
8649 float localnormal[3];
8660 float points[2][9][3];
8664 decalsystem = &ent->decalsystem;
8666 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8668 R_DecalSystem_Reset(&ent->decalsystem);
8672 if (!model->brush.data_nodes && !cl_decals_models.integer)
8674 if (decalsystem->model)
8675 R_DecalSystem_Reset(decalsystem);
8679 if (decalsystem->model != model)
8680 R_DecalSystem_Reset(decalsystem);
8681 decalsystem->model = model;
8683 RSurf_ActiveModelEntity(ent, false, false, false);
8685 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8686 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8687 VectorNormalize(localnormal);
8688 localsize = worldsize*rsurface.inversematrixscale;
8689 ilocalsize = 1.0f / localsize;
8690 localmins[0] = localorigin[0] - localsize;
8691 localmins[1] = localorigin[1] - localsize;
8692 localmins[2] = localorigin[2] - localsize;
8693 localmaxs[0] = localorigin[0] + localsize;
8694 localmaxs[1] = localorigin[1] + localsize;
8695 localmaxs[2] = localorigin[2] + localsize;
8697 //VectorCopy(localnormal, planes[4]);
8698 //VectorVectors(planes[4], planes[2], planes[0]);
8699 AnglesFromVectors(angles, localnormal, NULL, false);
8700 AngleVectors(angles, planes[0], planes[2], planes[4]);
8701 VectorNegate(planes[0], planes[1]);
8702 VectorNegate(planes[2], planes[3]);
8703 VectorNegate(planes[4], planes[5]);
8704 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8705 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8706 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8707 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8708 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8709 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8714 matrix4x4_t forwardprojection;
8715 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8716 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8721 float projectionvector[4][3];
8722 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8723 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8724 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8725 projectionvector[0][0] = planes[0][0] * ilocalsize;
8726 projectionvector[0][1] = planes[1][0] * ilocalsize;
8727 projectionvector[0][2] = planes[2][0] * ilocalsize;
8728 projectionvector[1][0] = planes[0][1] * ilocalsize;
8729 projectionvector[1][1] = planes[1][1] * ilocalsize;
8730 projectionvector[1][2] = planes[2][1] * ilocalsize;
8731 projectionvector[2][0] = planes[0][2] * ilocalsize;
8732 projectionvector[2][1] = planes[1][2] * ilocalsize;
8733 projectionvector[2][2] = planes[2][2] * ilocalsize;
8734 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8735 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8736 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8737 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8741 dynamic = model->surfmesh.isanimated;
8742 vertex3f = rsurface.modelvertex3f;
8743 numsurfacelist = model->nummodelsurfaces;
8744 surfacelist = model->sortedmodelsurfaces;
8745 surfaces = model->data_surfaces;
8746 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8748 surfaceindex = surfacelist[surfacelistindex];
8749 surface = surfaces + surfaceindex;
8750 // skip transparent surfaces
8751 texture = surface->texture;
8752 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8754 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8756 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8758 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8759 numvertices = surface->num_vertices;
8760 numtriangles = surface->num_triangles;
8761 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8763 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8765 index = 3*e[cornerindex];
8766 VectorCopy(vertex3f + index, v[cornerindex]);
8769 //TriangleNormal(v[0], v[1], v[2], normal);
8770 //if (DotProduct(normal, localnormal) < 0.0f)
8772 // clip by each of the box planes formed from the projection matrix
8773 // if anything survives, we emit the decal
8774 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]);
8777 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]);
8780 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]);
8783 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]);
8786 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]);
8789 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]);
8792 // some part of the triangle survived, so we have to accept it...
8795 // dynamic always uses the original triangle
8797 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8799 index = 3*e[cornerindex];
8800 VectorCopy(vertex3f + index, v[cornerindex]);
8803 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8805 // convert vertex positions to texcoords
8806 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8807 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8808 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8809 // calculate distance fade from the projection origin
8810 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8811 f = bound(0.0f, f, 1.0f);
8812 c[cornerindex][0] = r * f;
8813 c[cornerindex][1] = g * f;
8814 c[cornerindex][2] = b * f;
8815 c[cornerindex][3] = 1.0f;
8816 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8819 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);
8821 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8822 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);
8827 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8828 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)
8830 int renderentityindex;
8833 entity_render_t *ent;
8835 if (!cl_decals_newsystem.integer)
8838 worldmins[0] = worldorigin[0] - worldsize;
8839 worldmins[1] = worldorigin[1] - worldsize;
8840 worldmins[2] = worldorigin[2] - worldsize;
8841 worldmaxs[0] = worldorigin[0] + worldsize;
8842 worldmaxs[1] = worldorigin[1] + worldsize;
8843 worldmaxs[2] = worldorigin[2] + worldsize;
8845 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8847 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8849 ent = r_refdef.scene.entities[renderentityindex];
8850 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8853 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8857 typedef struct r_decalsystem_splatqueue_s
8866 r_decalsystem_splatqueue_t;
8868 int r_decalsystem_numqueued = 0;
8869 #define MAX_DECALSYSTEM_QUEUE 1024
8870 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8872 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)
8874 r_decalsystem_splatqueue_t *queue;
8876 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8879 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8880 VectorCopy(worldorigin, queue->worldorigin);
8881 VectorCopy(worldnormal, queue->worldnormal);
8882 Vector4Set(queue->color, r, g, b, a);
8883 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8884 queue->worldsize = worldsize;
8885 queue->decalsequence = cl.decalsequence++;
8888 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8891 r_decalsystem_splatqueue_t *queue;
8893 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8894 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);
8895 r_decalsystem_numqueued = 0;
8898 extern cvar_t cl_decals_max;
8899 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8902 decalsystem_t *decalsystem = &ent->decalsystem;
8909 if (!decalsystem->numdecals)
8912 if (r_showsurfaces.integer)
8915 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8917 R_DecalSystem_Reset(decalsystem);
8921 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
8922 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
8924 if (decalsystem->lastupdatetime)
8925 frametime = (cl.time - decalsystem->lastupdatetime);
8928 decalsystem->lastupdatetime = cl.time;
8929 decal = decalsystem->decals;
8930 numdecals = decalsystem->numdecals;
8932 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8934 if (decal->color4ub[0][3])
8936 decal->lived += frametime;
8937 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
8939 memset(decal, 0, sizeof(*decal));
8940 if (decalsystem->freedecal > i)
8941 decalsystem->freedecal = i;
8945 decal = decalsystem->decals;
8946 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
8949 // collapse the array by shuffling the tail decals into the gaps
8952 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
8953 decalsystem->freedecal++;
8954 if (decalsystem->freedecal == numdecals)
8956 decal[decalsystem->freedecal] = decal[--numdecals];
8959 decalsystem->numdecals = numdecals;
8963 // if there are no decals left, reset decalsystem
8964 R_DecalSystem_Reset(decalsystem);
8968 extern skinframe_t *decalskinframe;
8969 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8972 decalsystem_t *decalsystem = &ent->decalsystem;
8982 const unsigned char *surfacevisible = r_refdef.viewcache.world_surfacevisible;
8985 numdecals = decalsystem->numdecals;
8989 if (r_showsurfaces.integer)
8992 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8994 R_DecalSystem_Reset(decalsystem);
8998 // if the model is static it doesn't matter what value we give for
8999 // wantnormals and wanttangents, so this logic uses only rules applicable
9000 // to a model, knowing that they are meaningless otherwise
9001 if (ent == r_refdef.scene.worldentity)
9002 RSurf_ActiveWorldEntity();
9004 RSurf_ActiveModelEntity(ent, false, false, false);
9006 decalsystem->lastupdatetime = cl.time;
9007 decal = decalsystem->decals;
9009 fadedelay = cl_decals_time.value;
9010 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9012 // update vertex positions for animated models
9013 v3f = decalsystem->vertex3f;
9014 c4f = decalsystem->color4f;
9015 t2f = decalsystem->texcoord2f;
9016 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9018 if (!decal->color4ub[0][3])
9021 if (decal->surfaceindex >= 0 && !surfacevisible[decal->surfaceindex])
9024 // update color values for fading decals
9025 if (decal->lived >= cl_decals_time.value)
9027 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9028 alpha *= (1.0f/255.0f);
9031 alpha = 1.0f/255.0f;
9033 c4f[ 0] = decal->color4ub[0][0] * alpha;
9034 c4f[ 1] = decal->color4ub[0][1] * alpha;
9035 c4f[ 2] = decal->color4ub[0][2] * alpha;
9037 c4f[ 4] = decal->color4ub[1][0] * alpha;
9038 c4f[ 5] = decal->color4ub[1][1] * alpha;
9039 c4f[ 6] = decal->color4ub[1][2] * alpha;
9041 c4f[ 8] = decal->color4ub[2][0] * alpha;
9042 c4f[ 9] = decal->color4ub[2][1] * alpha;
9043 c4f[10] = decal->color4ub[2][2] * alpha;
9046 t2f[0] = decal->texcoord2f[0][0];
9047 t2f[1] = decal->texcoord2f[0][1];
9048 t2f[2] = decal->texcoord2f[1][0];
9049 t2f[3] = decal->texcoord2f[1][1];
9050 t2f[4] = decal->texcoord2f[2][0];
9051 t2f[5] = decal->texcoord2f[2][1];
9053 // update vertex positions for animated models
9054 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9056 e = rsurface.modelelement3i + 3*decal->triangleindex;
9057 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9058 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9059 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9063 VectorCopy(decal->vertex3f[0], v3f);
9064 VectorCopy(decal->vertex3f[1], v3f + 3);
9065 VectorCopy(decal->vertex3f[2], v3f + 6);
9076 r_refdef.stats.drawndecals += numtris;
9077 // now render the decals all at once
9078 // (this assumes they all use one particle font texture!)
9079 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);
9080 R_Mesh_ResetTextureState();
9081 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9082 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9083 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9084 R_SetupGenericShader(true);
9085 GL_DepthMask(false);
9086 GL_DepthRange(0, 1);
9087 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9089 GL_CullFace(GL_NONE);
9090 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9091 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
9092 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
9093 GL_LockArrays(0, numtris * 3);
9094 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9095 GL_LockArrays(0, 0);
9099 static void R_DrawModelDecals(void)
9103 // fade faster when there are too many decals
9104 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9105 for (i = 0;i < r_refdef.scene.numentities;i++)
9106 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9108 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9109 for (i = 0;i < r_refdef.scene.numentities;i++)
9110 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9111 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9113 R_DecalSystem_ApplySplatEntitiesQueue();
9115 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9116 for (i = 0;i < r_refdef.scene.numentities;i++)
9117 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9119 r_refdef.stats.totaldecals += numdecals;
9121 if (r_showsurfaces.integer)
9124 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9126 for (i = 0;i < r_refdef.scene.numentities;i++)
9128 if (!r_refdef.viewcache.entityvisible[i])
9130 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9131 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9135 void R_DrawDebugModel(void)
9137 entity_render_t *ent = rsurface.entity;
9138 int i, j, k, l, flagsmask;
9139 const int *elements;
9141 const msurface_t *surface;
9142 dp_model_t *model = ent->model;
9145 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9147 R_Mesh_ColorPointer(NULL, 0, 0);
9148 R_Mesh_ResetTextureState();
9149 R_SetupGenericShader(false);
9150 GL_DepthRange(0, 1);
9151 GL_DepthTest(!r_showdisabledepthtest.integer);
9152 GL_DepthMask(false);
9153 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9155 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
9157 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
9158 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
9160 if (brush->colbrushf && brush->colbrushf->numtriangles)
9162 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
9163 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);
9164 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
9167 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
9169 if (surface->num_collisiontriangles)
9171 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
9172 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);
9173 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
9178 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9180 if (r_showtris.integer || r_shownormals.integer)
9182 if (r_showdisabledepthtest.integer)
9184 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9185 GL_DepthMask(false);
9189 GL_BlendFunc(GL_ONE, GL_ZERO);
9192 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9194 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9196 rsurface.texture = R_GetCurrentTexture(surface->texture);
9197 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9199 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
9200 if (r_showtris.value > 0)
9202 if (!rsurface.texture->currentlayers->depthmask)
9203 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
9204 else if (ent == r_refdef.scene.worldentity)
9205 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
9207 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
9208 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
9209 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
9210 R_Mesh_ColorPointer(NULL, 0, 0);
9211 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
9212 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9213 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
9214 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);
9215 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9218 if (r_shownormals.value < 0)
9221 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9223 VectorCopy(rsurface.vertex3f + l * 3, v);
9224 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9225 qglVertex3f(v[0], v[1], v[2]);
9226 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
9227 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9228 qglVertex3f(v[0], v[1], v[2]);
9233 if (r_shownormals.value > 0)
9236 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9238 VectorCopy(rsurface.vertex3f + l * 3, v);
9239 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9240 qglVertex3f(v[0], v[1], v[2]);
9241 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
9242 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9243 qglVertex3f(v[0], v[1], v[2]);
9248 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9250 VectorCopy(rsurface.vertex3f + l * 3, v);
9251 GL_Color(0, r_refdef.view.colorscale, 0, 1);
9252 qglVertex3f(v[0], v[1], v[2]);
9253 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
9254 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9255 qglVertex3f(v[0], v[1], v[2]);
9260 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9262 VectorCopy(rsurface.vertex3f + l * 3, v);
9263 GL_Color(0, 0, r_refdef.view.colorscale, 1);
9264 qglVertex3f(v[0], v[1], v[2]);
9265 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
9266 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9267 qglVertex3f(v[0], v[1], v[2]);
9274 rsurface.texture = NULL;
9278 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
9279 int r_maxsurfacelist = 0;
9280 const msurface_t **r_surfacelist = NULL;
9281 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9283 int i, j, endj, f, flagsmask;
9285 dp_model_t *model = r_refdef.scene.worldmodel;
9286 msurface_t *surfaces;
9287 unsigned char *update;
9288 int numsurfacelist = 0;
9292 if (r_maxsurfacelist < model->num_surfaces)
9294 r_maxsurfacelist = model->num_surfaces;
9296 Mem_Free((msurface_t**)r_surfacelist);
9297 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9300 RSurf_ActiveWorldEntity();
9302 surfaces = model->data_surfaces;
9303 update = model->brushq1.lightmapupdateflags;
9305 // update light styles on this submodel
9306 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9308 model_brush_lightstyleinfo_t *style;
9309 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9311 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9313 int *list = style->surfacelist;
9314 style->value = r_refdef.scene.lightstylevalue[style->style];
9315 for (j = 0;j < style->numsurfaces;j++)
9316 update[list[j]] = true;
9321 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9326 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9332 rsurface.uselightmaptexture = false;
9333 rsurface.texture = NULL;
9334 rsurface.rtlight = NULL;
9336 // add visible surfaces to draw list
9337 for (i = 0;i < model->nummodelsurfaces;i++)
9339 j = model->sortedmodelsurfaces[i];
9340 if (r_refdef.viewcache.world_surfacevisible[j])
9341 r_surfacelist[numsurfacelist++] = surfaces + j;
9343 // update lightmaps if needed
9345 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9346 if (r_refdef.viewcache.world_surfacevisible[j])
9348 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9349 // don't do anything if there were no surfaces
9350 if (!numsurfacelist)
9352 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9355 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9356 GL_AlphaTest(false);
9358 // add to stats if desired
9359 if (r_speeds.integer && !skysurfaces && !depthonly)
9361 r_refdef.stats.world_surfaces += numsurfacelist;
9362 for (j = 0;j < numsurfacelist;j++)
9363 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9366 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9369 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9371 int i, j, endj, f, flagsmask;
9373 dp_model_t *model = ent->model;
9374 msurface_t *surfaces;
9375 unsigned char *update;
9376 int numsurfacelist = 0;
9380 if (r_maxsurfacelist < model->num_surfaces)
9382 r_maxsurfacelist = model->num_surfaces;
9384 Mem_Free((msurface_t **)r_surfacelist);
9385 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9388 // if the model is static it doesn't matter what value we give for
9389 // wantnormals and wanttangents, so this logic uses only rules applicable
9390 // to a model, knowing that they are meaningless otherwise
9391 if (ent == r_refdef.scene.worldentity)
9392 RSurf_ActiveWorldEntity();
9393 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9394 RSurf_ActiveModelEntity(ent, false, false, false);
9396 RSurf_ActiveModelEntity(ent, true, true, true);
9398 RSurf_ActiveModelEntity(ent, false, false, false);
9401 switch (vid.renderpath)
9403 case RENDERPATH_GL20:
9404 RSurf_ActiveModelEntity(ent, true, true, false);
9406 case RENDERPATH_GL13:
9407 case RENDERPATH_GL11:
9408 RSurf_ActiveModelEntity(ent, true, false, false);
9413 surfaces = model->data_surfaces;
9414 update = model->brushq1.lightmapupdateflags;
9416 // update light styles
9417 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9419 model_brush_lightstyleinfo_t *style;
9420 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9422 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9424 int *list = style->surfacelist;
9425 style->value = r_refdef.scene.lightstylevalue[style->style];
9426 for (j = 0;j < style->numsurfaces;j++)
9427 update[list[j]] = true;
9432 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9437 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9443 rsurface.uselightmaptexture = false;
9444 rsurface.texture = NULL;
9445 rsurface.rtlight = NULL;
9447 // add visible surfaces to draw list
9448 for (i = 0;i < model->nummodelsurfaces;i++)
9449 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9450 // don't do anything if there were no surfaces
9451 if (!numsurfacelist)
9453 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9456 // update lightmaps if needed
9458 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9460 R_BuildLightMap(ent, surfaces + j);
9461 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9462 GL_AlphaTest(false);
9464 // add to stats if desired
9465 if (r_speeds.integer && !skysurfaces && !depthonly)
9467 r_refdef.stats.entities_surfaces += numsurfacelist;
9468 for (j = 0;j < numsurfacelist;j++)
9469 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9472 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9475 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
9477 static texture_t texture;
9478 static msurface_t surface;
9479 const msurface_t *surfacelist = &surface;
9481 // fake enough texture and surface state to render this geometry
9483 texture.update_lastrenderframe = -1; // regenerate this texture
9484 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9485 texture.currentskinframe = skinframe;
9486 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9487 texture.specularscalemod = 1;
9488 texture.specularpowermod = 1;
9490 surface.texture = &texture;
9491 surface.num_triangles = numtriangles;
9492 surface.num_firsttriangle = firsttriangle;
9493 surface.num_vertices = numvertices;
9494 surface.num_firstvertex = firstvertex;
9497 rsurface.texture = R_GetCurrentTexture(surface.texture);
9498 rsurface.uselightmaptexture = false;
9499 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);