2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
33 qboolean r_loadnormalmap;
42 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
43 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
44 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
45 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
46 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
47 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
48 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
49 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
51 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
52 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
53 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
54 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
55 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
57 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
59 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
60 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
61 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
62 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
63 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
64 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
65 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
66 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
67 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
68 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
69 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
71 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
72 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
73 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
74 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
75 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
76 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
77 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
78 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
79 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
80 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
81 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
82 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
83 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
84 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
85 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
86 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
87 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
88 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
89 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
90 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
91 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
92 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
93 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
94 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
95 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
96 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
97 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
99 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
102 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
103 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
104 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
105 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
106 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
107 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
108 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
110 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
112 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
113 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
114 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
115 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
116 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
117 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
118 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
119 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
120 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
121 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
123 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)"};
124 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
125 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"};
126 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
127 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
129 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
130 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
131 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
132 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
134 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
135 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
136 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
137 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
138 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
139 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
140 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
142 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
143 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
144 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
145 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)"};
147 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"};
149 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"};
151 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
153 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
154 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
155 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"};
156 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
157 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
158 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
159 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
161 extern cvar_t v_glslgamma;
163 extern qboolean v_flipped_state;
165 static struct r_bloomstate_s
170 int bloomwidth, bloomheight;
172 int screentexturewidth, screentextureheight;
173 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
175 int bloomtexturewidth, bloomtextureheight;
176 rtexture_t *texture_bloom;
178 // arrays for rendering the screen passes
179 float screentexcoord2f[8];
180 float bloomtexcoord2f[8];
181 float offsettexcoord2f[8];
183 r_viewport_t viewport;
187 r_waterstate_t r_waterstate;
189 /// shadow volume bsp struct with automatically growing nodes buffer
192 rtexture_t *r_texture_blanknormalmap;
193 rtexture_t *r_texture_white;
194 rtexture_t *r_texture_grey128;
195 rtexture_t *r_texture_black;
196 rtexture_t *r_texture_notexture;
197 rtexture_t *r_texture_whitecube;
198 rtexture_t *r_texture_normalizationcube;
199 rtexture_t *r_texture_fogattenuation;
200 rtexture_t *r_texture_gammaramps;
201 unsigned int r_texture_gammaramps_serial;
202 //rtexture_t *r_texture_fogintensity;
204 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
205 unsigned int r_numqueries;
206 unsigned int r_maxqueries;
208 typedef struct r_qwskincache_s
210 char name[MAX_QPATH];
211 skinframe_t *skinframe;
215 static r_qwskincache_t *r_qwskincache;
216 static int r_qwskincache_size;
218 /// vertex coordinates for a quad that covers the screen exactly
219 const float r_screenvertex3f[12] =
227 extern void R_DrawModelShadows(void);
229 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
232 for (i = 0;i < verts;i++)
243 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
246 for (i = 0;i < verts;i++)
256 // FIXME: move this to client?
259 if (gamemode == GAME_NEHAHRA)
261 Cvar_Set("gl_fogenable", "0");
262 Cvar_Set("gl_fogdensity", "0.2");
263 Cvar_Set("gl_fogred", "0.3");
264 Cvar_Set("gl_foggreen", "0.3");
265 Cvar_Set("gl_fogblue", "0.3");
267 r_refdef.fog_density = 0;
268 r_refdef.fog_red = 0;
269 r_refdef.fog_green = 0;
270 r_refdef.fog_blue = 0;
271 r_refdef.fog_alpha = 1;
272 r_refdef.fog_start = 0;
273 r_refdef.fog_end = 16384;
274 r_refdef.fog_height = 1<<30;
275 r_refdef.fog_fadedepth = 128;
278 static void R_BuildBlankTextures(void)
280 unsigned char data[4];
281 data[2] = 128; // normal X
282 data[1] = 128; // normal Y
283 data[0] = 255; // normal Z
284 data[3] = 128; // height
285 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
290 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
295 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
300 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
303 static void R_BuildNoTexture(void)
306 unsigned char pix[16][16][4];
307 // this makes a light grey/dark grey checkerboard texture
308 for (y = 0;y < 16;y++)
310 for (x = 0;x < 16;x++)
312 if ((y < 8) ^ (x < 8))
328 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
331 static void R_BuildWhiteCube(void)
333 unsigned char data[6*1*1*4];
334 memset(data, 255, sizeof(data));
335 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
338 static void R_BuildNormalizationCube(void)
342 vec_t s, t, intensity;
344 unsigned char data[6][NORMSIZE][NORMSIZE][4];
345 for (side = 0;side < 6;side++)
347 for (y = 0;y < NORMSIZE;y++)
349 for (x = 0;x < NORMSIZE;x++)
351 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
352 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
387 intensity = 127.0f / sqrt(DotProduct(v, v));
388 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
389 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
390 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
391 data[side][y][x][3] = 255;
395 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
398 static void R_BuildFogTexture(void)
402 unsigned char data1[FOGWIDTH][4];
403 //unsigned char data2[FOGWIDTH][4];
406 r_refdef.fogmasktable_start = r_refdef.fog_start;
407 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
408 r_refdef.fogmasktable_range = r_refdef.fogrange;
409 r_refdef.fogmasktable_density = r_refdef.fog_density;
411 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
412 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
414 d = (x * r - r_refdef.fogmasktable_start);
415 if(developer.integer >= 100)
416 Con_Printf("%f ", d);
418 if (r_fog_exp2.integer)
419 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
421 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
422 if(developer.integer >= 100)
423 Con_Printf(" : %f ", alpha);
424 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
425 if(developer.integer >= 100)
426 Con_Printf(" = %f\n", alpha);
427 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
430 for (x = 0;x < FOGWIDTH;x++)
432 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
437 //data2[x][0] = 255 - b;
438 //data2[x][1] = 255 - b;
439 //data2[x][2] = 255 - b;
442 if (r_texture_fogattenuation)
444 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
445 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
449 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);
450 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
454 static const char *builtinshaderstring =
455 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
456 "// written by Forest 'LordHavoc' Hale\n"
458 "// enable various extensions depending on permutation:\n"
460 "#ifdef USESHADOWMAPRECT\n"
461 "# extension GL_ARB_texture_rectangle : enable\n"
464 "#ifdef USESHADOWMAP2D\n"
465 "# ifdef GL_EXT_gpu_shader4\n"
466 "# extension GL_EXT_gpu_shader4 : enable\n"
468 "# ifdef GL_ARB_texture_gather\n"
469 "# extension GL_ARB_texture_gather : enable\n"
471 "# ifdef GL_AMD_texture_texture4\n"
472 "# extension GL_AMD_texture_texture4 : enable\n"
477 "#ifdef USESHADOWMAPCUBE\n"
478 "# extension GL_EXT_gpu_shader4 : enable\n"
481 "#ifdef USESHADOWSAMPLER\n"
482 "# extension GL_ARB_shadow : enable\n"
485 "// common definitions between vertex shader and fragment shader:\n"
487 "//#ifdef __GLSL_CG_DATA_TYPES\n"
488 "//# define myhalf half\n"
489 "//# define myhalf2 half2\n"
490 "//# define myhalf3half3\n"
491 "//# define myhalf4 half4\n"
493 "# define myhalf float\n"
494 "# define myhalf2 vec2\n"
495 "# define myhalf3 vec3\n"
496 "# define myhalf4 vec4\n"
499 "#ifdef USEFOGINSIDE\n"
502 "# ifdef USEFOGOUTSIDE\n"
507 "#ifdef MODE_DEPTH_OR_SHADOW\n"
509 "# ifdef VERTEX_SHADER\n"
512 " gl_Position = ftransform();\n"
517 "#ifdef MODE_SHOWDEPTH\n"
518 "# ifdef VERTEX_SHADER\n"
521 " gl_Position = ftransform();\n"
522 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
525 "# ifdef FRAGMENT_SHADER\n"
528 " gl_FragColor = gl_Color;\n"
532 "#else // !MODE_SHOWDEPTH\n"
534 "#ifdef MODE_POSTPROCESS\n"
535 "# ifdef VERTEX_SHADER\n"
538 " gl_FrontColor = gl_Color;\n"
539 " gl_Position = ftransform();\n"
540 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
542 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
546 "# ifdef FRAGMENT_SHADER\n"
548 "uniform sampler2D Texture_First;\n"
550 "uniform sampler2D Texture_Second;\n"
552 "#ifdef USEGAMMARAMPS\n"
553 "uniform sampler2D Texture_GammaRamps;\n"
555 "#ifdef USESATURATION\n"
556 "uniform float Saturation;\n"
558 "#ifdef USEVIEWTINT\n"
559 "uniform vec4 TintColor;\n"
561 "//uncomment these if you want to use them:\n"
562 "uniform vec4 UserVec1;\n"
563 "// uniform vec4 UserVec2;\n"
564 "// uniform vec4 UserVec3;\n"
565 "// uniform vec4 UserVec4;\n"
566 "// uniform float ClientTime;\n"
567 "uniform vec2 PixelSize;\n"
570 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
572 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
574 "#ifdef USEVIEWTINT\n"
575 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
578 "#ifdef USEPOSTPROCESSING\n"
579 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
580 "// 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"
581 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
582 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
583 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
584 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
585 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
586 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
589 "#ifdef USESATURATION\n"
590 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
591 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
592 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
593 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
596 "#ifdef USEGAMMARAMPS\n"
597 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
598 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
599 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
606 "#ifdef MODE_GENERIC\n"
607 "# ifdef VERTEX_SHADER\n"
610 " gl_FrontColor = gl_Color;\n"
611 "# ifdef USEDIFFUSE\n"
612 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
614 "# ifdef USESPECULAR\n"
615 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
617 " gl_Position = ftransform();\n"
620 "# ifdef FRAGMENT_SHADER\n"
622 "# ifdef USEDIFFUSE\n"
623 "uniform sampler2D Texture_First;\n"
625 "# ifdef USESPECULAR\n"
626 "uniform sampler2D Texture_Second;\n"
631 " gl_FragColor = gl_Color;\n"
632 "# ifdef USEDIFFUSE\n"
633 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
636 "# ifdef USESPECULAR\n"
637 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
639 "# ifdef USECOLORMAPPING\n"
640 " gl_FragColor *= tex2;\n"
643 " gl_FragColor += tex2;\n"
645 "# ifdef USEVERTEXTEXTUREBLEND\n"
646 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
651 "#else // !MODE_GENERIC\n"
652 "#ifdef MODE_BLOOMBLUR\n"
653 "# ifdef VERTEX_SHADER\n"
656 " gl_FrontColor = gl_Color;\n"
657 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
658 " gl_Position = ftransform();\n"
661 "# ifdef FRAGMENT_SHADER\n"
663 "uniform sampler2D Texture_First;\n"
664 "uniform vec4 BloomBlur_Parameters;\n"
669 " vec2 tc = gl_TexCoord[0].xy;\n"
670 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
671 " tc += BloomBlur_Parameters.xy;\n"
672 " for (i = 1;i < SAMPLES;i++)\n"
674 " color += texture2D(Texture_First, tc).rgb;\n"
675 " tc += BloomBlur_Parameters.xy;\n"
677 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
681 "#else // !MODE_BLOOMBLUR\n"
683 "varying vec2 TexCoord;\n"
684 "#ifdef USEVERTEXTEXTUREBLEND\n"
685 "varying vec2 TexCoord2;\n"
687 "varying vec2 TexCoordLightmap;\n"
689 "#ifdef MODE_LIGHTSOURCE\n"
690 "varying vec3 CubeVector;\n"
693 "#ifdef MODE_LIGHTSOURCE\n"
694 "varying vec3 LightVector;\n"
696 "#ifdef MODE_LIGHTDIRECTION\n"
697 "varying vec3 LightVector;\n"
700 "varying vec3 EyeVector;\n"
702 "varying vec3 EyeVectorModelSpace;\n"
703 "varying float FogPlaneVertexDist;\n"
706 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
707 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
708 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
710 "#ifdef MODE_WATER\n"
711 "varying vec4 ModelViewProjectionPosition;\n"
713 "#ifdef MODE_REFRACTION\n"
714 "varying vec4 ModelViewProjectionPosition;\n"
716 "#ifdef USEREFLECTION\n"
717 "varying vec4 ModelViewProjectionPosition;\n"
724 "// vertex shader specific:\n"
725 "#ifdef VERTEX_SHADER\n"
727 "uniform vec3 LightPosition;\n"
728 "uniform vec3 EyePosition;\n"
729 "uniform vec3 LightDir;\n"
730 "uniform vec4 FogPlane;\n"
732 "// 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"
736 " gl_FrontColor = gl_Color;\n"
737 " // copy the surface texcoord\n"
738 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
739 "#ifdef USEVERTEXTEXTUREBLEND\n"
740 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
742 "#ifndef MODE_LIGHTSOURCE\n"
743 "# ifndef MODE_LIGHTDIRECTION\n"
744 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
748 "#ifdef MODE_LIGHTSOURCE\n"
749 " // transform vertex position into light attenuation/cubemap space\n"
750 " // (-1 to +1 across the light box)\n"
751 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
753 " // transform unnormalized light direction into tangent space\n"
754 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
755 " // normalize it per pixel)\n"
756 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
757 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
758 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
759 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
762 "#ifdef MODE_LIGHTDIRECTION\n"
763 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
764 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
765 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
768 " // transform unnormalized eye direction into tangent space\n"
770 " vec3 EyeVectorModelSpace;\n"
772 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
773 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
774 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
775 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
778 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
781 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
782 " VectorS = gl_MultiTexCoord1.xyz;\n"
783 " VectorT = gl_MultiTexCoord2.xyz;\n"
784 " VectorR = gl_MultiTexCoord3.xyz;\n"
787 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
788 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
789 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
790 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
793 "// transform vertex to camera space, using ftransform to match non-VS\n"
795 " gl_Position = ftransform();\n"
797 "#ifdef MODE_WATER\n"
798 " ModelViewProjectionPosition = gl_Position;\n"
800 "#ifdef MODE_REFRACTION\n"
801 " ModelViewProjectionPosition = gl_Position;\n"
803 "#ifdef USEREFLECTION\n"
804 " ModelViewProjectionPosition = gl_Position;\n"
808 "#endif // VERTEX_SHADER\n"
813 "// fragment shader specific:\n"
814 "#ifdef FRAGMENT_SHADER\n"
816 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
817 "uniform sampler2D Texture_Normal;\n"
818 "uniform sampler2D Texture_Color;\n"
819 "uniform sampler2D Texture_Gloss;\n"
820 "uniform sampler2D Texture_Glow;\n"
821 "uniform sampler2D Texture_SecondaryNormal;\n"
822 "uniform sampler2D Texture_SecondaryColor;\n"
823 "uniform sampler2D Texture_SecondaryGloss;\n"
824 "uniform sampler2D Texture_SecondaryGlow;\n"
825 "uniform sampler2D Texture_Pants;\n"
826 "uniform sampler2D Texture_Shirt;\n"
827 "uniform sampler2D Texture_FogMask;\n"
828 "uniform sampler2D Texture_Lightmap;\n"
829 "uniform sampler2D Texture_Deluxemap;\n"
830 "uniform sampler2D Texture_Refraction;\n"
831 "uniform sampler2D Texture_Reflection;\n"
832 "uniform sampler2D Texture_Attenuation;\n"
833 "uniform samplerCube Texture_Cube;\n"
835 "#define showshadowmap 0\n"
837 "#ifdef USESHADOWMAPRECT\n"
838 "# ifdef USESHADOWSAMPLER\n"
839 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
841 "uniform sampler2DRect Texture_ShadowMapRect;\n"
845 "#ifdef USESHADOWMAP2D\n"
846 "# ifdef USESHADOWSAMPLER\n"
847 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
849 "uniform sampler2D Texture_ShadowMap2D;\n"
853 "#ifdef USESHADOWMAPVSDCT\n"
854 "uniform samplerCube Texture_CubeProjection;\n"
857 "#ifdef USESHADOWMAPCUBE\n"
858 "# ifdef USESHADOWSAMPLER\n"
859 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
861 "uniform samplerCube Texture_ShadowMapCube;\n"
865 "uniform myhalf3 LightColor;\n"
866 "uniform myhalf3 AmbientColor;\n"
867 "uniform myhalf3 DiffuseColor;\n"
868 "uniform myhalf3 SpecularColor;\n"
869 "uniform myhalf3 Color_Pants;\n"
870 "uniform myhalf3 Color_Shirt;\n"
871 "uniform myhalf3 FogColor;\n"
873 "uniform myhalf4 TintColor;\n"
876 "//#ifdef MODE_WATER\n"
877 "uniform vec4 DistortScaleRefractReflect;\n"
878 "uniform vec4 ScreenScaleRefractReflect;\n"
879 "uniform vec4 ScreenCenterRefractReflect;\n"
880 "uniform myhalf4 RefractColor;\n"
881 "uniform myhalf4 ReflectColor;\n"
882 "uniform myhalf ReflectFactor;\n"
883 "uniform myhalf ReflectOffset;\n"
885 "//# ifdef MODE_REFRACTION\n"
886 "//uniform vec4 DistortScaleRefractReflect;\n"
887 "//uniform vec4 ScreenScaleRefractReflect;\n"
888 "//uniform vec4 ScreenCenterRefractReflect;\n"
889 "//uniform myhalf4 RefractColor;\n"
890 "//# ifdef USEREFLECTION\n"
891 "//uniform myhalf4 ReflectColor;\n"
894 "//# ifdef USEREFLECTION\n"
895 "//uniform vec4 DistortScaleRefractReflect;\n"
896 "//uniform vec4 ScreenScaleRefractReflect;\n"
897 "//uniform vec4 ScreenCenterRefractReflect;\n"
898 "//uniform myhalf4 ReflectColor;\n"
903 "uniform myhalf3 GlowColor;\n"
904 "uniform myhalf SceneBrightness;\n"
906 "uniform float OffsetMapping_Scale;\n"
907 "uniform float OffsetMapping_Bias;\n"
908 "uniform float FogRangeRecip;\n"
909 "uniform float FogPlaneViewDist;\n"
910 "uniform float FogHeightFade;\n"
912 "uniform myhalf AmbientScale;\n"
913 "uniform myhalf DiffuseScale;\n"
914 "uniform myhalf SpecularScale;\n"
915 "uniform myhalf SpecularPower;\n"
917 "#ifdef USEOFFSETMAPPING\n"
918 "vec2 OffsetMapping(vec2 TexCoord)\n"
920 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
921 " // 14 sample relief mapping: linear search and then binary search\n"
922 " // this basically steps forward a small amount repeatedly until it finds\n"
923 " // itself inside solid, then jitters forward and back using decreasing\n"
924 " // amounts to find the impact\n"
925 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
926 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
927 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
928 " vec3 RT = vec3(TexCoord, 1);\n"
929 " OffsetVector *= 0.1;\n"
930 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
931 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
932 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
933 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
934 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
935 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
936 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
937 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
938 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
939 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
940 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
941 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
942 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
943 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
946 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
947 " // this basically moves forward the full distance, and then backs up based\n"
948 " // on height of samples\n"
949 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
950 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
951 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
952 " TexCoord += OffsetVector;\n"
953 " OffsetVector *= 0.333;\n"
954 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
955 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
956 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
957 " return TexCoord;\n"
960 "#endif // USEOFFSETMAPPING\n"
962 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
963 "uniform vec2 ShadowMap_TextureScale;\n"
964 "uniform vec4 ShadowMap_Parameters;\n"
967 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
968 "vec3 GetShadowMapTC2D(vec3 dir)\n"
970 " vec3 adir = abs(dir);\n"
971 "# ifndef USESHADOWMAPVSDCT\n"
975 " if (adir.x > adir.y)\n"
977 " if (adir.x > adir.z) // X\n"
981 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
987 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
992 " if (adir.y > adir.z) // Y\n"
996 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1002 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1006 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1007 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1008 " stc.z += ShadowMap_Parameters.z;\n"
1009 "# if showshadowmap\n"
1010 " stc.xy *= ShadowMap_TextureScale;\n"
1014 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1015 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1016 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1017 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1018 " stc.z += ShadowMap_Parameters.z;\n"
1019 "# if showshadowmap\n"
1020 " stc.xy *= ShadowMap_TextureScale;\n"
1025 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1027 "#ifdef USESHADOWMAPCUBE\n"
1028 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1030 " vec3 adir = abs(dir);\n"
1031 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1035 "#if !showshadowmap\n"
1036 "# ifdef USESHADOWMAPRECT\n"
1037 "float ShadowMapCompare(vec3 dir)\n"
1039 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1041 "# ifdef USESHADOWSAMPLER\n"
1043 "# ifdef USESHADOWMAPPCF\n"
1044 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1045 " 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"
1047 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1052 "# ifdef USESHADOWMAPPCF\n"
1053 "# if USESHADOWMAPPCF > 1\n"
1054 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1055 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1056 " 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"
1057 " 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"
1058 " 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"
1059 " 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"
1060 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1061 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1063 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1064 " vec2 offset = fract(shadowmaptc.xy);\n"
1065 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1066 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1067 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1068 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1069 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1072 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1080 "# ifdef USESHADOWMAP2D\n"
1081 "float ShadowMapCompare(vec3 dir)\n"
1083 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1086 "# ifdef USESHADOWSAMPLER\n"
1087 "# ifdef USESHADOWMAPPCF\n"
1088 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1089 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1090 " 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"
1092 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1095 "# ifdef USESHADOWMAPPCF\n"
1096 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1097 "# ifdef GL_ARB_texture_gather\n"
1098 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1100 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1102 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1103 " center *= ShadowMap_TextureScale;\n"
1104 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1105 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1106 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1107 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1108 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1109 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1110 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1112 "# ifdef GL_EXT_gpu_shader4\n"
1113 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1115 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1117 "# if USESHADOWMAPPCF > 1\n"
1118 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1119 " center *= ShadowMap_TextureScale;\n"
1120 " 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"
1121 " 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"
1122 " 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"
1123 " 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"
1124 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1125 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1127 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1128 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1129 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1130 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1131 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1132 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1136 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1143 "# ifdef USESHADOWMAPCUBE\n"
1144 "float ShadowMapCompare(vec3 dir)\n"
1146 " // apply depth texture cubemap as light filter\n"
1147 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1149 "# ifdef USESHADOWSAMPLER\n"
1150 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1152 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1159 "#ifdef MODE_WATER\n"
1164 "#ifdef USEOFFSETMAPPING\n"
1165 " // apply offsetmapping\n"
1166 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1167 "#define TexCoord TexCoordOffset\n"
1170 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1171 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1172 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1173 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1174 " // FIXME temporary hack to detect the case that the reflection\n"
1175 " // gets blackened at edges due to leaving the area that contains actual\n"
1177 " // Remove this 'ack once we have a better way to stop this thing from\n"
1179 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1180 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1181 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1182 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1183 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1184 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1185 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1186 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1187 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1188 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1189 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1190 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1193 "#else // !MODE_WATER\n"
1194 "#ifdef MODE_REFRACTION\n"
1196 "// refraction pass\n"
1199 "#ifdef USEOFFSETMAPPING\n"
1200 " // apply offsetmapping\n"
1201 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1202 "#define TexCoord TexCoordOffset\n"
1205 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1206 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1207 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1208 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1209 " // FIXME temporary hack to detect the case that the reflection\n"
1210 " // gets blackened at edges due to leaving the area that contains actual\n"
1212 " // Remove this 'ack once we have a better way to stop this thing from\n"
1214 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1215 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1216 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1217 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1218 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1219 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1222 "#else // !MODE_REFRACTION\n"
1225 "#ifdef USEOFFSETMAPPING\n"
1226 " // apply offsetmapping\n"
1227 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1228 "#define TexCoord TexCoordOffset\n"
1231 " // combine the diffuse textures (base, pants, shirt)\n"
1232 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1233 "#ifdef USECOLORMAPPING\n"
1234 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1236 "#ifdef USEVERTEXTEXTUREBLEND\n"
1237 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1238 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1239 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1240 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1242 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1245 "#ifdef USEDIFFUSE\n"
1246 " // get the surface normal and the gloss color\n"
1247 "# ifdef USEVERTEXTEXTUREBLEND\n"
1248 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1249 "# ifdef USESPECULAR\n"
1250 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1253 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1254 "# ifdef USESPECULAR\n"
1255 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1262 "#ifdef MODE_LIGHTSOURCE\n"
1263 " // light source\n"
1265 " // calculate surface normal, light normal, and specular normal\n"
1266 " // compute color intensity for the two textures (colormap and glossmap)\n"
1267 " // scale by light color and attenuation as efficiently as possible\n"
1268 " // (do as much scalar math as possible rather than vector math)\n"
1269 "# ifdef USEDIFFUSE\n"
1270 " // get the light normal\n"
1271 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1273 "# ifdef USESPECULAR\n"
1274 "# ifndef USEEXACTSPECULARMATH\n"
1275 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1278 " // calculate directional shading\n"
1279 "# ifdef USEEXACTSPECULARMATH\n"
1280 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
1282 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * glosscolor);\n"
1285 "# ifdef USEDIFFUSE\n"
1286 " // calculate directional shading\n"
1287 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1289 " // calculate directionless shading\n"
1290 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1294 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1295 "#if !showshadowmap\n"
1296 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1300 "# ifdef USECUBEFILTER\n"
1301 " // apply light cubemap filter\n"
1302 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1303 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1305 "#endif // MODE_LIGHTSOURCE\n"
1310 "#ifdef MODE_LIGHTDIRECTION\n"
1311 " // directional model lighting\n"
1312 "# ifdef USEDIFFUSE\n"
1313 " // get the light normal\n"
1314 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1316 "# ifdef USESPECULAR\n"
1317 " // calculate directional shading\n"
1318 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1319 "# ifdef USEEXACTSPECULARMATH\n"
1320 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1322 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1323 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1326 "# ifdef USEDIFFUSE\n"
1328 " // calculate directional shading\n"
1329 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1331 " color.rgb *= AmbientColor;\n"
1334 "#endif // MODE_LIGHTDIRECTION\n"
1339 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1340 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1342 " // get the light normal\n"
1343 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1344 " myhalf3 diffusenormal;\n"
1345 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1346 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1347 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1348 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1349 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1350 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1351 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1352 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1353 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1354 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1355 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1356 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1357 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1358 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1359 "# ifdef USESPECULAR\n"
1360 "# ifdef USEEXACTSPECULARMATH\n"
1361 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1363 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1364 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1368 " // apply lightmap color\n"
1369 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1370 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1375 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1376 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1378 " // get the light normal\n"
1379 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1380 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1381 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1382 "# ifdef USESPECULAR\n"
1383 "# ifdef USEEXACTSPECULARMATH\n"
1384 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1386 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1387 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1391 " // apply lightmap color\n"
1392 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1393 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1398 "#ifdef MODE_LIGHTMAP\n"
1399 " // apply lightmap color\n"
1400 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1401 "#endif // MODE_LIGHTMAP\n"
1406 "#ifdef MODE_VERTEXCOLOR\n"
1407 " // apply lightmap color\n"
1408 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1409 "#endif // MODE_VERTEXCOLOR\n"
1414 "#ifdef MODE_FLATCOLOR\n"
1415 "#endif // MODE_FLATCOLOR\n"
1423 " color *= TintColor;\n"
1426 "#ifdef USEVERTEXTEXTUREBLEND\n"
1427 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1429 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1433 " color.rgb *= SceneBrightness;\n"
1435 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1438 "#ifdef USEFOGOUTSIDE\n"
1439 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1441 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1443 "// float FogHeightFade1 = -0.5/1024.0;\n"
1444 "// if (FogPlaneViewDist >= 0.0)\n"
1445 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade1);\n"
1447 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade1);\n"
1448 "//# ifdef USEFOGABOVE\n"
1449 "// if (FogPlaneViewDist >= 0.0)\n"
1450 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist);\n"
1452 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist));\n"
1453 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1454 "// fogfrac *= min(1.0, (max(0.0, fade*FogPlaneVertexDist) + max(0.0, fade*FogPlaneViewDist)));\n"
1455 "// fogfrac *= min(1.0, (max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1456 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1458 " //fogfrac *= min(1.0, max(0.0, (max(-2048, min(0, FogPlaneVertexDist)) + max(-2048, min(0, FogPlaneViewDist)))/-2048.0));\n"
1459 " //float fade = -0.5/128.0;\n"
1460 " //fogfrac *= max(0.0, min(1.0, fade*FogPlaneVertexDist)) + max(0.0, min(1.0, fade*FogPlaneViewDist));\n"
1461 " //fogfrac *= max(0.0, min(1.0, FogHeightFade1*FogPlaneVertexDist)) + max(0.0, min(1.0, FogHeightFade1*FogPlaneViewDist));\n"
1462 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1463 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1464 " //fogfrac *= min(1.0, min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1465 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1466 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1467 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1469 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0))));\n"
1472 " // 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"
1473 "#ifdef USEREFLECTION\n"
1474 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1475 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1476 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1477 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1478 " // FIXME temporary hack to detect the case that the reflection\n"
1479 " // gets blackened at edges due to leaving the area that contains actual\n"
1481 " // Remove this 'ack once we have a better way to stop this thing from\n"
1483 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1484 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1485 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1486 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1487 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1488 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1491 " gl_FragColor = vec4(color);\n"
1493 "#if showshadowmap\n"
1494 "# ifdef USESHADOWMAPRECT\n"
1495 "# ifdef USESHADOWSAMPLER\n"
1496 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1498 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1501 "# ifdef USESHADOWMAP2D\n"
1502 "# ifdef USESHADOWSAMPLER\n"
1503 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1505 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1509 "# ifdef USESHADOWMAPCUBE\n"
1510 "# ifdef USESHADOWSAMPLER\n"
1511 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1513 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1518 "#endif // !MODE_REFRACTION\n"
1519 "#endif // !MODE_WATER\n"
1521 "#endif // FRAGMENT_SHADER\n"
1523 "#endif // !MODE_BLOOMBLUR\n"
1524 "#endif // !MODE_GENERIC\n"
1525 "#endif // !MODE_POSTPROCESS\n"
1526 "#endif // !MODE_SHOWDEPTH\n"
1527 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1530 typedef struct shaderpermutationinfo_s
1532 const char *pretext;
1535 shaderpermutationinfo_t;
1537 typedef struct shadermodeinfo_s
1539 const char *vertexfilename;
1540 const char *geometryfilename;
1541 const char *fragmentfilename;
1542 const char *pretext;
1547 typedef enum shaderpermutation_e
1549 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1550 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1551 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1552 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1553 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1554 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1555 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1556 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1557 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1558 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1559 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1560 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1561 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1562 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1563 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1564 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1565 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1566 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1567 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1568 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1569 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1570 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1571 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1572 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1573 SHADERPERMUTATION_LIMIT = 1<<24, ///< size of permutations array
1574 SHADERPERMUTATION_COUNT = 24 ///< size of shaderpermutationinfo array
1576 shaderpermutation_t;
1578 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1579 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1581 {"#define USEDIFFUSE\n", " diffuse"},
1582 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1583 {"#define USEVIEWTINT\n", " viewtint"},
1584 {"#define USECOLORMAPPING\n", " colormapping"},
1585 {"#define USESATURATION\n", " saturation"},
1586 {"#define USEFOGINSIDE\n", " foginside"},
1587 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1588 {"#define USEGAMMARAMPS\n", " gammaramps"},
1589 {"#define USECUBEFILTER\n", " cubefilter"},
1590 {"#define USEGLOW\n", " glow"},
1591 {"#define USEBLOOM\n", " bloom"},
1592 {"#define USESPECULAR\n", " specular"},
1593 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1594 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1595 {"#define USEREFLECTION\n", " reflection"},
1596 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1597 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1598 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1599 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1600 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1601 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1602 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1603 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1604 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1607 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1608 typedef enum shadermode_e
1610 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1611 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1612 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1613 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1614 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1615 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1616 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1617 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1618 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1619 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1620 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1621 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1622 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1627 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1628 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1630 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1631 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1632 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1633 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1634 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1635 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1636 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1637 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1638 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1639 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1640 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1641 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1642 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1645 struct r_glsl_permutation_s;
1646 typedef struct r_glsl_permutation_s
1648 /// hash lookup data
1649 struct r_glsl_permutation_s *hashnext;
1651 unsigned int permutation;
1653 /// indicates if we have tried compiling this permutation already
1655 /// 0 if compilation failed
1657 /// locations of detected uniforms in program object, or -1 if not found
1658 int loc_Texture_First;
1659 int loc_Texture_Second;
1660 int loc_Texture_GammaRamps;
1661 int loc_Texture_Normal;
1662 int loc_Texture_Color;
1663 int loc_Texture_Gloss;
1664 int loc_Texture_Glow;
1665 int loc_Texture_SecondaryNormal;
1666 int loc_Texture_SecondaryColor;
1667 int loc_Texture_SecondaryGloss;
1668 int loc_Texture_SecondaryGlow;
1669 int loc_Texture_Pants;
1670 int loc_Texture_Shirt;
1671 int loc_Texture_FogMask;
1672 int loc_Texture_Lightmap;
1673 int loc_Texture_Deluxemap;
1674 int loc_Texture_Attenuation;
1675 int loc_Texture_Cube;
1676 int loc_Texture_Refraction;
1677 int loc_Texture_Reflection;
1678 int loc_Texture_ShadowMapRect;
1679 int loc_Texture_ShadowMapCube;
1680 int loc_Texture_ShadowMap2D;
1681 int loc_Texture_CubeProjection;
1683 int loc_LightPosition;
1684 int loc_EyePosition;
1685 int loc_Color_Pants;
1686 int loc_Color_Shirt;
1688 int loc_FogPlaneViewDist;
1689 int loc_FogRangeRecip;
1690 int loc_FogHeightFade;
1691 int loc_AmbientScale;
1692 int loc_DiffuseScale;
1693 int loc_SpecularScale;
1694 int loc_SpecularPower;
1696 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1697 int loc_OffsetMapping_Scale;
1699 int loc_AmbientColor;
1700 int loc_DiffuseColor;
1701 int loc_SpecularColor;
1703 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1704 int loc_GammaCoeff; ///< 1 / gamma
1705 int loc_DistortScaleRefractReflect;
1706 int loc_ScreenScaleRefractReflect;
1707 int loc_ScreenCenterRefractReflect;
1708 int loc_RefractColor;
1709 int loc_ReflectColor;
1710 int loc_ReflectFactor;
1711 int loc_ReflectOffset;
1719 int loc_ShadowMap_TextureScale;
1720 int loc_ShadowMap_Parameters;
1722 r_glsl_permutation_t;
1724 #define SHADERPERMUTATION_HASHSIZE 256
1726 /// information about each possible shader permutation
1727 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1728 /// currently selected permutation
1729 r_glsl_permutation_t *r_glsl_permutation;
1730 /// storage for permutations linked in the hash table
1731 memexpandablearray_t r_glsl_permutationarray;
1733 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1735 //unsigned int hashdepth = 0;
1736 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1737 r_glsl_permutation_t *p;
1738 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1740 if (p->mode == mode && p->permutation == permutation)
1742 //if (hashdepth > 10)
1743 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1748 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1750 p->permutation = permutation;
1751 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1752 r_glsl_permutationhash[mode][hashindex] = p;
1753 //if (hashdepth > 10)
1754 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1758 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1761 if (!filename || !filename[0])
1763 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1766 if (printfromdisknotice)
1767 Con_DPrint("from disk... ");
1768 return shaderstring;
1770 else if (!strcmp(filename, "glsl/default.glsl"))
1772 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1773 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1775 return shaderstring;
1778 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1781 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1782 int vertstrings_count = 0;
1783 int geomstrings_count = 0;
1784 int fragstrings_count = 0;
1785 char *vertexstring, *geometrystring, *fragmentstring;
1786 const char *vertstrings_list[32+3];
1787 const char *geomstrings_list[32+3];
1788 const char *fragstrings_list[32+3];
1789 char permutationname[256];
1796 permutationname[0] = 0;
1797 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1798 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1799 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1801 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1803 // the first pretext is which type of shader to compile as
1804 // (later these will all be bound together as a program object)
1805 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1806 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1807 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1809 // the second pretext is the mode (for example a light source)
1810 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1811 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1812 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1813 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1815 // now add all the permutation pretexts
1816 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1818 if (permutation & (1<<i))
1820 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1821 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1822 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1823 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1827 // keep line numbers correct
1828 vertstrings_list[vertstrings_count++] = "\n";
1829 geomstrings_list[geomstrings_count++] = "\n";
1830 fragstrings_list[fragstrings_count++] = "\n";
1834 // now append the shader text itself
1835 vertstrings_list[vertstrings_count++] = vertexstring;
1836 geomstrings_list[geomstrings_count++] = geometrystring;
1837 fragstrings_list[fragstrings_count++] = fragmentstring;
1839 // if any sources were NULL, clear the respective list
1841 vertstrings_count = 0;
1842 if (!geometrystring)
1843 geomstrings_count = 0;
1844 if (!fragmentstring)
1845 fragstrings_count = 0;
1847 // compile the shader program
1848 if (vertstrings_count + geomstrings_count + fragstrings_count)
1849 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1853 qglUseProgramObjectARB(p->program);CHECKGLERROR
1854 // look up all the uniform variable names we care about, so we don't
1855 // have to look them up every time we set them
1856 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1857 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1858 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1859 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1860 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1861 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1862 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1863 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1864 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1865 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1866 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1867 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1868 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1869 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1870 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1871 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1872 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1873 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1874 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1875 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1876 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1877 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1878 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1879 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1880 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1881 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1882 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1883 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1884 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1885 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
1886 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
1887 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1888 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
1889 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1890 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1891 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1892 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1893 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1894 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1895 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1896 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1897 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1898 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1899 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1900 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1901 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1902 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1903 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1904 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1905 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1906 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1907 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1908 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1909 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1910 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1911 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1912 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1913 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1914 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1915 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1916 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1917 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1918 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1919 // initialize the samplers to refer to the texture units we use
1920 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1921 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1922 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1923 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1924 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1925 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1926 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1927 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1928 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1929 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1930 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1931 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1932 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1933 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1934 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1935 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1936 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1937 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1938 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1939 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1940 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1941 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1942 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1943 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1945 if (developer.integer)
1946 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1949 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1953 Mem_Free(vertexstring);
1955 Mem_Free(geometrystring);
1957 Mem_Free(fragmentstring);
1960 void R_GLSL_Restart_f(void)
1962 unsigned int i, limit;
1963 r_glsl_permutation_t *p;
1964 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1965 for (i = 0;i < limit;i++)
1967 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1969 GL_Backend_FreeProgram(p->program);
1970 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1973 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1976 void R_GLSL_DumpShader_f(void)
1980 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1983 Con_Printf("failed to write to glsl/default.glsl\n");
1987 FS_Print(file, "/* The engine may define the following macros:\n");
1988 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1989 for (i = 0;i < SHADERMODE_COUNT;i++)
1990 FS_Print(file, shadermodeinfo[i].pretext);
1991 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1992 FS_Print(file, shaderpermutationinfo[i].pretext);
1993 FS_Print(file, "*/\n");
1994 FS_Print(file, builtinshaderstring);
1997 Con_Printf("glsl/default.glsl written\n");
2000 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
2002 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2003 if (r_glsl_permutation != perm)
2005 r_glsl_permutation = perm;
2006 if (!r_glsl_permutation->program)
2008 if (!r_glsl_permutation->compiled)
2009 R_GLSL_CompilePermutation(perm, mode, permutation);
2010 if (!r_glsl_permutation->program)
2012 // remove features until we find a valid permutation
2014 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2016 // reduce i more quickly whenever it would not remove any bits
2017 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2018 if (!(permutation & j))
2021 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2022 if (!r_glsl_permutation->compiled)
2023 R_GLSL_CompilePermutation(perm, mode, permutation);
2024 if (r_glsl_permutation->program)
2027 if (i >= SHADERPERMUTATION_COUNT)
2029 Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2030 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2031 qglUseProgramObjectARB(0);CHECKGLERROR
2032 return; // no bit left to clear, entire mode is broken
2037 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2041 void R_SetupGenericShader(qboolean usetexture)
2043 if (vid.support.arb_fragment_shader)
2046 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2047 else if (r_glsl_permutation)
2049 r_glsl_permutation = NULL;
2050 qglUseProgramObjectARB(0);CHECKGLERROR
2055 void R_SetupGenericTwoTextureShader(int texturemode)
2057 if (vid.support.arb_fragment_shader)
2060 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))));
2061 else if (r_glsl_permutation)
2063 r_glsl_permutation = NULL;
2064 qglUseProgramObjectARB(0);CHECKGLERROR
2067 if (!r_glsl_permutation)
2068 R_Mesh_TexCombine(1, GL_DECAL, GL_DECAL, 1, 1);
2071 void R_SetupDepthOrShadowShader(void)
2073 if (vid.support.arb_fragment_shader)
2076 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2077 else if (r_glsl_permutation)
2079 r_glsl_permutation = NULL;
2080 qglUseProgramObjectARB(0);CHECKGLERROR
2085 void R_SetupShowDepthShader(void)
2087 if (vid.support.arb_fragment_shader)
2090 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2091 else if (r_glsl_permutation)
2093 r_glsl_permutation = NULL;
2094 qglUseProgramObjectARB(0);CHECKGLERROR
2099 extern rtexture_t *r_shadow_attenuationgradienttexture;
2100 extern rtexture_t *r_shadow_attenuation2dtexture;
2101 extern rtexture_t *r_shadow_attenuation3dtexture;
2102 extern qboolean r_shadow_usingshadowmaprect;
2103 extern qboolean r_shadow_usingshadowmapcube;
2104 extern qboolean r_shadow_usingshadowmap2d;
2105 extern float r_shadow_shadowmap_texturescale[2];
2106 extern float r_shadow_shadowmap_parameters[4];
2107 extern qboolean r_shadow_shadowmapvsdct;
2108 extern qboolean r_shadow_shadowmapsampler;
2109 extern int r_shadow_shadowmappcf;
2110 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2112 // select a permutation of the lighting shader appropriate to this
2113 // combination of texture, entity, light source, and fogging, only use the
2114 // minimum features necessary to avoid wasting rendering time in the
2115 // fragment shader on features that are not being used
2116 unsigned int permutation = 0;
2117 unsigned int mode = 0;
2118 // TODO: implement geometry-shader based shadow volumes someday
2119 if (r_glsl_offsetmapping.integer)
2121 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2122 if (r_glsl_offsetmapping_reliefmapping.integer)
2123 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2125 if (rsurfacepass == RSURFPASS_BACKGROUND)
2127 // distorted background
2128 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2129 mode = SHADERMODE_WATER;
2131 mode = SHADERMODE_REFRACTION;
2133 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2136 mode = SHADERMODE_LIGHTSOURCE;
2137 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2138 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2139 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2140 permutation |= SHADERPERMUTATION_CUBEFILTER;
2141 if (diffusescale > 0)
2142 permutation |= SHADERPERMUTATION_DIFFUSE;
2143 if (specularscale > 0)
2144 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2145 if (r_refdef.fogenabled)
2146 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2147 if (rsurface.texture->colormapping)
2148 permutation |= SHADERPERMUTATION_COLORMAPPING;
2149 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2151 if (r_shadow_usingshadowmaprect)
2152 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2153 if (r_shadow_usingshadowmap2d)
2154 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2155 if (r_shadow_usingshadowmapcube)
2156 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2157 else if(r_shadow_shadowmapvsdct)
2158 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2160 if (r_shadow_shadowmapsampler)
2161 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2162 if (r_shadow_shadowmappcf > 1)
2163 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2164 else if (r_shadow_shadowmappcf)
2165 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2168 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2170 // unshaded geometry (fullbright or ambient model lighting)
2171 mode = SHADERMODE_FLATCOLOR;
2172 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2173 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2174 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2175 permutation |= SHADERPERMUTATION_GLOW;
2176 if (r_refdef.fogenabled)
2177 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2178 if (rsurface.texture->colormapping)
2179 permutation |= SHADERPERMUTATION_COLORMAPPING;
2180 if (r_glsl_offsetmapping.integer)
2182 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2183 if (r_glsl_offsetmapping_reliefmapping.integer)
2184 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2186 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2187 permutation |= SHADERPERMUTATION_REFLECTION;
2189 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2191 // directional model lighting
2192 mode = SHADERMODE_LIGHTDIRECTION;
2193 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2194 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2195 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2196 permutation |= SHADERPERMUTATION_GLOW;
2197 permutation |= SHADERPERMUTATION_DIFFUSE;
2198 if (specularscale > 0)
2199 permutation |= SHADERPERMUTATION_SPECULAR;
2200 if (r_refdef.fogenabled)
2201 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2202 if (rsurface.texture->colormapping)
2203 permutation |= SHADERPERMUTATION_COLORMAPPING;
2204 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2205 permutation |= SHADERPERMUTATION_REFLECTION;
2207 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2209 // ambient model lighting
2210 mode = SHADERMODE_LIGHTDIRECTION;
2211 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2212 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2213 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2214 permutation |= SHADERPERMUTATION_GLOW;
2215 if (r_refdef.fogenabled)
2216 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2217 if (rsurface.texture->colormapping)
2218 permutation |= SHADERPERMUTATION_COLORMAPPING;
2219 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2220 permutation |= SHADERPERMUTATION_REFLECTION;
2225 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2227 // deluxemapping (light direction texture)
2228 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2229 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2231 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2232 permutation |= SHADERPERMUTATION_DIFFUSE;
2233 if (specularscale > 0)
2234 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2236 else if (r_glsl_deluxemapping.integer >= 2)
2238 // fake deluxemapping (uniform light direction in tangentspace)
2239 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2240 permutation |= SHADERPERMUTATION_DIFFUSE;
2241 if (specularscale > 0)
2242 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2244 else if (rsurface.uselightmaptexture)
2246 // ordinary lightmapping (q1bsp, q3bsp)
2247 mode = SHADERMODE_LIGHTMAP;
2251 // ordinary vertex coloring (q3bsp)
2252 mode = SHADERMODE_VERTEXCOLOR;
2254 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2255 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2256 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2257 permutation |= SHADERPERMUTATION_GLOW;
2258 if (r_refdef.fogenabled)
2259 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2260 if (rsurface.texture->colormapping)
2261 permutation |= SHADERPERMUTATION_COLORMAPPING;
2262 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2263 permutation |= SHADERPERMUTATION_REFLECTION;
2265 if(permutation & SHADERPERMUTATION_SPECULAR)
2266 if(r_shadow_glossexact.integer)
2267 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2268 R_SetupShader_SetPermutation(mode, permutation);
2269 if (mode == SHADERMODE_LIGHTSOURCE)
2271 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2272 if (permutation & SHADERPERMUTATION_DIFFUSE)
2274 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2275 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2276 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2277 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2281 // ambient only is simpler
2282 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
2283 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2284 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2285 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2287 // additive passes are only darkened by fog, not tinted
2288 if (r_glsl_permutation->loc_FogColor >= 0)
2289 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2290 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2291 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2295 if (mode == SHADERMODE_LIGHTDIRECTION)
2297 if (r_glsl_permutation->loc_AmbientColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale * 0.5f, rsurface.modellight_ambient[1] * ambientscale * 0.5f, rsurface.modellight_ambient[2] * ambientscale * 0.5f);
2298 if (r_glsl_permutation->loc_DiffuseColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale * 0.5f, rsurface.modellight_diffuse[1] * diffusescale * 0.5f, rsurface.modellight_diffuse[2] * diffusescale * 0.5f);
2299 if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
2300 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2304 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2305 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2306 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2308 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
2309 if (r_glsl_permutation->loc_GlowColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_GlowColor, rsurface.glowmod[0] * r_hdr_glowintensity.value, rsurface.glowmod[1] * r_hdr_glowintensity.value, rsurface.glowmod[2] * r_hdr_glowintensity.value);
2310 // additive passes are only darkened by fog, not tinted
2311 if (r_glsl_permutation->loc_FogColor >= 0)
2313 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2314 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2316 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2318 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2319 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2320 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2321 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2322 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2323 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2324 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2326 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2327 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2328 if (r_glsl_permutation->loc_Color_Pants >= 0)
2330 if (rsurface.texture->currentskinframe->pants)
2331 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2333 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2335 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2337 if (rsurface.texture->currentskinframe->shirt)
2338 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2340 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2342 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2343 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2344 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2345 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2346 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2348 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2352 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2354 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2358 #define SKINFRAME_HASH 1024
2362 int loadsequence; // incremented each level change
2363 memexpandablearray_t array;
2364 skinframe_t *hash[SKINFRAME_HASH];
2367 r_skinframe_t r_skinframe;
2369 void R_SkinFrame_PrepareForPurge(void)
2371 r_skinframe.loadsequence++;
2372 // wrap it without hitting zero
2373 if (r_skinframe.loadsequence >= 200)
2374 r_skinframe.loadsequence = 1;
2377 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2381 // mark the skinframe as used for the purging code
2382 skinframe->loadsequence = r_skinframe.loadsequence;
2385 void R_SkinFrame_Purge(void)
2389 for (i = 0;i < SKINFRAME_HASH;i++)
2391 for (s = r_skinframe.hash[i];s;s = s->next)
2393 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2395 if (s->merged == s->base)
2397 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2398 R_PurgeTexture(s->stain );s->stain = NULL;
2399 R_PurgeTexture(s->merged);s->merged = NULL;
2400 R_PurgeTexture(s->base );s->base = NULL;
2401 R_PurgeTexture(s->pants );s->pants = NULL;
2402 R_PurgeTexture(s->shirt );s->shirt = NULL;
2403 R_PurgeTexture(s->nmap );s->nmap = NULL;
2404 R_PurgeTexture(s->gloss );s->gloss = NULL;
2405 R_PurgeTexture(s->glow );s->glow = NULL;
2406 R_PurgeTexture(s->fog );s->fog = NULL;
2407 s->loadsequence = 0;
2413 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2415 char basename[MAX_QPATH];
2417 Image_StripImageExtension(name, basename, sizeof(basename));
2419 if( last == NULL ) {
2421 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2422 item = r_skinframe.hash[hashindex];
2427 // linearly search through the hash bucket
2428 for( ; item ; item = item->next ) {
2429 if( !strcmp( item->basename, basename ) ) {
2436 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2440 char basename[MAX_QPATH];
2442 Image_StripImageExtension(name, basename, sizeof(basename));
2444 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2445 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2446 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2450 rtexture_t *dyntexture;
2451 // check whether its a dynamic texture
2452 dyntexture = CL_GetDynTexture( basename );
2453 if (!add && !dyntexture)
2455 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2456 memset(item, 0, sizeof(*item));
2457 strlcpy(item->basename, basename, sizeof(item->basename));
2458 item->base = dyntexture; // either NULL or dyntexture handle
2459 item->textureflags = textureflags;
2460 item->comparewidth = comparewidth;
2461 item->compareheight = compareheight;
2462 item->comparecrc = comparecrc;
2463 item->next = r_skinframe.hash[hashindex];
2464 r_skinframe.hash[hashindex] = item;
2466 else if( item->base == NULL )
2468 rtexture_t *dyntexture;
2469 // check whether its a dynamic texture
2470 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
2471 dyntexture = CL_GetDynTexture( basename );
2472 item->base = dyntexture; // either NULL or dyntexture handle
2475 R_SkinFrame_MarkUsed(item);
2479 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2481 unsigned long long avgcolor[5], wsum; \
2489 for(pix = 0; pix < cnt; ++pix) \
2492 for(comp = 0; comp < 3; ++comp) \
2494 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2497 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2499 for(comp = 0; comp < 3; ++comp) \
2500 avgcolor[comp] += getpixel * w; \
2503 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2504 avgcolor[4] += getpixel; \
2506 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2508 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2509 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2510 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2511 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2514 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2517 unsigned char *pixels;
2518 unsigned char *bumppixels;
2519 unsigned char *basepixels = NULL;
2520 int basepixels_width;
2521 int basepixels_height;
2522 skinframe_t *skinframe;
2524 if (cls.state == ca_dedicated)
2527 // return an existing skinframe if already loaded
2528 // if loading of the first image fails, don't make a new skinframe as it
2529 // would cause all future lookups of this to be missing
2530 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2531 if (skinframe && skinframe->base)
2534 basepixels = loadimagepixelsbgra(name, complain, true);
2535 if (basepixels == NULL)
2538 if (developer_loading.integer)
2539 Con_Printf("loading skin \"%s\"\n", name);
2541 // we've got some pixels to store, so really allocate this new texture now
2543 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2544 skinframe->stain = NULL;
2545 skinframe->merged = NULL;
2546 skinframe->base = r_texture_notexture;
2547 skinframe->pants = NULL;
2548 skinframe->shirt = NULL;
2549 skinframe->nmap = r_texture_blanknormalmap;
2550 skinframe->gloss = NULL;
2551 skinframe->glow = NULL;
2552 skinframe->fog = NULL;
2553 skinframe->hasalpha = false;
2555 basepixels_width = image_width;
2556 basepixels_height = image_height;
2557 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);
2559 if (textureflags & TEXF_ALPHA)
2561 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2563 if (basepixels[j] < 255)
2565 skinframe->hasalpha = true;
2569 if (r_loadfog && skinframe->hasalpha)
2571 // has transparent pixels
2572 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2573 for (j = 0;j < image_width * image_height * 4;j += 4)
2578 pixels[j+3] = basepixels[j+3];
2580 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);
2585 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2586 //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]);
2588 // _norm is the name used by tenebrae and has been adopted as standard
2589 if (r_loadnormalmap)
2591 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2593 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);
2597 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2599 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2600 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2601 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2603 Mem_Free(bumppixels);
2605 else if (r_shadow_bumpscale_basetexture.value > 0)
2607 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2608 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2609 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);
2613 // _luma is supported for tenebrae compatibility
2614 // (I think it's a very stupid name, but oh well)
2615 // _glow is the preferred name
2616 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;}
2617 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;}
2618 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;}
2619 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;}
2622 Mem_Free(basepixels);
2627 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2628 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2631 unsigned char *temp1, *temp2;
2632 skinframe_t *skinframe;
2634 if (cls.state == ca_dedicated)
2637 // if already loaded just return it, otherwise make a new skinframe
2638 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2639 if (skinframe && skinframe->base)
2642 skinframe->stain = NULL;
2643 skinframe->merged = NULL;
2644 skinframe->base = r_texture_notexture;
2645 skinframe->pants = NULL;
2646 skinframe->shirt = NULL;
2647 skinframe->nmap = r_texture_blanknormalmap;
2648 skinframe->gloss = NULL;
2649 skinframe->glow = NULL;
2650 skinframe->fog = NULL;
2651 skinframe->hasalpha = false;
2653 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2657 if (developer_loading.integer)
2658 Con_Printf("loading 32bit skin \"%s\"\n", name);
2660 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2662 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2663 temp2 = temp1 + width * height * 4;
2664 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2665 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2668 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2669 if (textureflags & TEXF_ALPHA)
2671 for (i = 3;i < width * height * 4;i += 4)
2673 if (skindata[i] < 255)
2675 skinframe->hasalpha = true;
2679 if (r_loadfog && skinframe->hasalpha)
2681 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2682 memcpy(fogpixels, skindata, width * height * 4);
2683 for (i = 0;i < width * height * 4;i += 4)
2684 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2685 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2686 Mem_Free(fogpixels);
2690 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2691 //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]);
2696 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2700 skinframe_t *skinframe;
2702 if (cls.state == ca_dedicated)
2705 // if already loaded just return it, otherwise make a new skinframe
2706 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2707 if (skinframe && skinframe->base)
2710 skinframe->stain = NULL;
2711 skinframe->merged = NULL;
2712 skinframe->base = r_texture_notexture;
2713 skinframe->pants = NULL;
2714 skinframe->shirt = NULL;
2715 skinframe->nmap = r_texture_blanknormalmap;
2716 skinframe->gloss = NULL;
2717 skinframe->glow = NULL;
2718 skinframe->fog = NULL;
2719 skinframe->hasalpha = false;
2721 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2725 if (developer_loading.integer)
2726 Con_Printf("loading quake skin \"%s\"\n", name);
2728 // 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)
2729 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
2730 memcpy(skinframe->qpixels, skindata, width*height);
2731 skinframe->qwidth = width;
2732 skinframe->qheight = height;
2735 for (i = 0;i < width * height;i++)
2736 featuresmask |= palette_featureflags[skindata[i]];
2738 skinframe->hasalpha = false;
2739 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2740 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2741 skinframe->qgeneratemerged = true;
2742 skinframe->qgeneratebase = skinframe->qhascolormapping;
2743 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2745 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2746 //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]);
2751 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2755 unsigned char *skindata;
2757 if (!skinframe->qpixels)
2760 if (!skinframe->qhascolormapping)
2761 colormapped = false;
2765 if (!skinframe->qgeneratebase)
2770 if (!skinframe->qgeneratemerged)
2774 width = skinframe->qwidth;
2775 height = skinframe->qheight;
2776 skindata = skinframe->qpixels;
2778 if (skinframe->qgeneratenmap)
2780 unsigned char *temp1, *temp2;
2781 skinframe->qgeneratenmap = false;
2782 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2783 temp2 = temp1 + width * height * 4;
2784 // use either a custom palette or the quake palette
2785 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2786 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2787 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2791 if (skinframe->qgenerateglow)
2793 skinframe->qgenerateglow = false;
2794 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
2799 skinframe->qgeneratebase = false;
2800 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);
2801 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
2802 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
2806 skinframe->qgeneratemerged = false;
2807 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
2810 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
2812 Mem_Free(skinframe->qpixels);
2813 skinframe->qpixels = NULL;
2817 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)
2820 skinframe_t *skinframe;
2822 if (cls.state == ca_dedicated)
2825 // if already loaded just return it, otherwise make a new skinframe
2826 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2827 if (skinframe && skinframe->base)
2830 skinframe->stain = NULL;
2831 skinframe->merged = NULL;
2832 skinframe->base = r_texture_notexture;
2833 skinframe->pants = NULL;
2834 skinframe->shirt = NULL;
2835 skinframe->nmap = r_texture_blanknormalmap;
2836 skinframe->gloss = NULL;
2837 skinframe->glow = NULL;
2838 skinframe->fog = NULL;
2839 skinframe->hasalpha = false;
2841 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2845 if (developer_loading.integer)
2846 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2848 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
2849 if (textureflags & TEXF_ALPHA)
2851 for (i = 0;i < width * height;i++)
2853 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
2855 skinframe->hasalpha = true;
2859 if (r_loadfog && skinframe->hasalpha)
2860 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
2863 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2864 //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]);
2869 skinframe_t *R_SkinFrame_LoadMissing(void)
2871 skinframe_t *skinframe;
2873 if (cls.state == ca_dedicated)
2876 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2877 skinframe->stain = NULL;
2878 skinframe->merged = NULL;
2879 skinframe->base = r_texture_notexture;
2880 skinframe->pants = NULL;
2881 skinframe->shirt = NULL;
2882 skinframe->nmap = r_texture_blanknormalmap;
2883 skinframe->gloss = NULL;
2884 skinframe->glow = NULL;
2885 skinframe->fog = NULL;
2886 skinframe->hasalpha = false;
2888 skinframe->avgcolor[0] = rand() / RAND_MAX;
2889 skinframe->avgcolor[1] = rand() / RAND_MAX;
2890 skinframe->avgcolor[2] = rand() / RAND_MAX;
2891 skinframe->avgcolor[3] = 1;
2896 void R_Main_FreeViewCache(void)
2898 if (r_refdef.viewcache.entityvisible)
2899 Mem_Free(r_refdef.viewcache.entityvisible);
2900 if (r_refdef.viewcache.world_pvsbits)
2901 Mem_Free(r_refdef.viewcache.world_pvsbits);
2902 if (r_refdef.viewcache.world_leafvisible)
2903 Mem_Free(r_refdef.viewcache.world_leafvisible);
2904 if (r_refdef.viewcache.world_surfacevisible)
2905 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2906 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2909 void R_Main_ResizeViewCache(void)
2911 int numentities = r_refdef.scene.numentities;
2912 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
2913 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
2914 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
2915 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
2916 if (r_refdef.viewcache.maxentities < numentities)
2918 r_refdef.viewcache.maxentities = numentities;
2919 if (r_refdef.viewcache.entityvisible)
2920 Mem_Free(r_refdef.viewcache.entityvisible);
2921 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
2923 if (r_refdef.viewcache.world_numclusters != numclusters)
2925 r_refdef.viewcache.world_numclusters = numclusters;
2926 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
2927 if (r_refdef.viewcache.world_pvsbits)
2928 Mem_Free(r_refdef.viewcache.world_pvsbits);
2929 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
2931 if (r_refdef.viewcache.world_numleafs != numleafs)
2933 r_refdef.viewcache.world_numleafs = numleafs;
2934 if (r_refdef.viewcache.world_leafvisible)
2935 Mem_Free(r_refdef.viewcache.world_leafvisible);
2936 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
2938 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
2940 r_refdef.viewcache.world_numsurfaces = numsurfaces;
2941 if (r_refdef.viewcache.world_surfacevisible)
2942 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2943 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
2947 void gl_main_start(void)
2949 r_loadnormalmap = r_loadgloss = vid.support.arb_texture_env_dot3 || vid.support.arb_fragment_shader;
2954 memset(r_queries, 0, sizeof(r_queries));
2956 r_qwskincache = NULL;
2957 r_qwskincache_size = 0;
2959 // set up r_skinframe loading system for textures
2960 memset(&r_skinframe, 0, sizeof(r_skinframe));
2961 r_skinframe.loadsequence = 1;
2962 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2964 r_main_texturepool = R_AllocTexturePool();
2965 R_BuildBlankTextures();
2967 if (vid.support.arb_texture_cube_map)
2970 R_BuildNormalizationCube();
2972 r_texture_fogattenuation = NULL;
2973 r_texture_gammaramps = NULL;
2974 //r_texture_fogintensity = NULL;
2975 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2976 memset(&r_waterstate, 0, sizeof(r_waterstate));
2977 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2978 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2979 memset(&r_svbsp, 0, sizeof (r_svbsp));
2981 r_refdef.fogmasktable_density = 0;
2984 extern rtexture_t *loadingscreentexture;
2985 void gl_main_shutdown(void)
2987 R_Main_FreeViewCache();
2990 qglDeleteQueriesARB(r_maxqueries, r_queries);
2994 memset(r_queries, 0, sizeof(r_queries));
2996 r_qwskincache = NULL;
2997 r_qwskincache_size = 0;
2999 // clear out the r_skinframe state
3000 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3001 memset(&r_skinframe, 0, sizeof(r_skinframe));
3004 Mem_Free(r_svbsp.nodes);
3005 memset(&r_svbsp, 0, sizeof (r_svbsp));
3006 R_FreeTexturePool(&r_main_texturepool);
3007 loadingscreentexture = NULL;
3008 r_texture_blanknormalmap = NULL;
3009 r_texture_white = NULL;
3010 r_texture_grey128 = NULL;
3011 r_texture_black = NULL;
3012 r_texture_whitecube = NULL;
3013 r_texture_normalizationcube = NULL;
3014 r_texture_fogattenuation = NULL;
3015 r_texture_gammaramps = NULL;
3016 //r_texture_fogintensity = NULL;
3017 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3018 memset(&r_waterstate, 0, sizeof(r_waterstate));
3022 extern void CL_ParseEntityLump(char *entitystring);
3023 void gl_main_newmap(void)
3025 // FIXME: move this code to client
3027 char *entities, entname[MAX_QPATH];
3029 Mem_Free(r_qwskincache);
3030 r_qwskincache = NULL;
3031 r_qwskincache_size = 0;
3034 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
3035 l = (int)strlen(entname) - 4;
3036 if (l >= 0 && !strcmp(entname + l, ".bsp"))
3038 memcpy(entname + l, ".ent", 5);
3039 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3041 CL_ParseEntityLump(entities);
3046 if (cl.worldmodel->brush.entities)
3047 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3049 R_Main_FreeViewCache();
3052 void GL_Main_Init(void)
3054 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3056 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3057 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3058 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3059 if (gamemode == GAME_NEHAHRA)
3061 Cvar_RegisterVariable (&gl_fogenable);
3062 Cvar_RegisterVariable (&gl_fogdensity);
3063 Cvar_RegisterVariable (&gl_fogred);
3064 Cvar_RegisterVariable (&gl_foggreen);
3065 Cvar_RegisterVariable (&gl_fogblue);
3066 Cvar_RegisterVariable (&gl_fogstart);
3067 Cvar_RegisterVariable (&gl_fogend);
3068 Cvar_RegisterVariable (&gl_skyclip);
3070 Cvar_RegisterVariable(&r_motionblur);
3071 Cvar_RegisterVariable(&r_motionblur_maxblur);
3072 Cvar_RegisterVariable(&r_motionblur_bmin);
3073 Cvar_RegisterVariable(&r_motionblur_vmin);
3074 Cvar_RegisterVariable(&r_motionblur_vmax);
3075 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3076 Cvar_RegisterVariable(&r_motionblur_randomize);
3077 Cvar_RegisterVariable(&r_damageblur);
3078 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3079 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3080 Cvar_RegisterVariable(&r_equalize_entities_by);
3081 Cvar_RegisterVariable(&r_equalize_entities_to);
3082 Cvar_RegisterVariable(&r_animcache);
3083 Cvar_RegisterVariable(&r_depthfirst);
3084 Cvar_RegisterVariable(&r_useinfinitefarclip);
3085 Cvar_RegisterVariable(&r_farclip_base);
3086 Cvar_RegisterVariable(&r_farclip_world);
3087 Cvar_RegisterVariable(&r_nearclip);
3088 Cvar_RegisterVariable(&r_showbboxes);
3089 Cvar_RegisterVariable(&r_showsurfaces);
3090 Cvar_RegisterVariable(&r_showtris);
3091 Cvar_RegisterVariable(&r_shownormals);
3092 Cvar_RegisterVariable(&r_showlighting);
3093 Cvar_RegisterVariable(&r_showshadowvolumes);
3094 Cvar_RegisterVariable(&r_showcollisionbrushes);
3095 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3096 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3097 Cvar_RegisterVariable(&r_showdisabledepthtest);
3098 Cvar_RegisterVariable(&r_drawportals);
3099 Cvar_RegisterVariable(&r_drawentities);
3100 Cvar_RegisterVariable(&r_cullentities_trace);
3101 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3102 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3103 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3104 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3105 Cvar_RegisterVariable(&r_drawviewmodel);
3106 Cvar_RegisterVariable(&r_speeds);
3107 Cvar_RegisterVariable(&r_fullbrights);
3108 Cvar_RegisterVariable(&r_wateralpha);
3109 Cvar_RegisterVariable(&r_dynamic);
3110 Cvar_RegisterVariable(&r_fullbright);
3111 Cvar_RegisterVariable(&r_shadows);
3112 Cvar_RegisterVariable(&r_shadows_darken);
3113 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3114 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3115 Cvar_RegisterVariable(&r_shadows_throwdistance);
3116 Cvar_RegisterVariable(&r_shadows_throwdirection);
3117 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3118 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3119 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3120 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3121 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3122 Cvar_RegisterVariable(&r_fog_exp2);
3123 Cvar_RegisterVariable(&r_drawfog);
3124 Cvar_RegisterVariable(&r_textureunits);
3125 Cvar_RegisterVariable(&r_glsl);
3126 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3127 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3128 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3129 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3130 Cvar_RegisterVariable(&r_glsl_postprocess);
3131 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3132 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3133 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3134 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3135 Cvar_RegisterVariable(&r_water);
3136 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3137 Cvar_RegisterVariable(&r_water_clippingplanebias);
3138 Cvar_RegisterVariable(&r_water_refractdistort);
3139 Cvar_RegisterVariable(&r_water_reflectdistort);
3140 Cvar_RegisterVariable(&r_lerpsprites);
3141 Cvar_RegisterVariable(&r_lerpmodels);
3142 Cvar_RegisterVariable(&r_lerplightstyles);
3143 Cvar_RegisterVariable(&r_waterscroll);
3144 Cvar_RegisterVariable(&r_bloom);
3145 Cvar_RegisterVariable(&r_bloom_colorscale);
3146 Cvar_RegisterVariable(&r_bloom_brighten);
3147 Cvar_RegisterVariable(&r_bloom_blur);
3148 Cvar_RegisterVariable(&r_bloom_resolution);
3149 Cvar_RegisterVariable(&r_bloom_colorexponent);
3150 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3151 Cvar_RegisterVariable(&r_hdr);
3152 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3153 Cvar_RegisterVariable(&r_hdr_glowintensity);
3154 Cvar_RegisterVariable(&r_hdr_range);
3155 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3156 Cvar_RegisterVariable(&developer_texturelogging);
3157 Cvar_RegisterVariable(&gl_lightmaps);
3158 Cvar_RegisterVariable(&r_test);
3159 Cvar_RegisterVariable(&r_batchmode);
3160 Cvar_RegisterVariable(&r_glsl_saturation);
3161 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3162 Cvar_SetValue("r_fullbrights", 0);
3163 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3165 Cvar_RegisterVariable(&r_track_sprites);
3166 Cvar_RegisterVariable(&r_track_sprites_flags);
3167 Cvar_RegisterVariable(&r_track_sprites_scalew);
3168 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3171 extern void R_Textures_Init(void);
3172 extern void GL_Draw_Init(void);
3173 extern void GL_Main_Init(void);
3174 extern void R_Shadow_Init(void);
3175 extern void R_Sky_Init(void);
3176 extern void GL_Surf_Init(void);
3177 extern void R_Particles_Init(void);
3178 extern void R_Explosion_Init(void);
3179 extern void gl_backend_init(void);
3180 extern void Sbar_Init(void);
3181 extern void R_LightningBeams_Init(void);
3182 extern void Mod_RenderInit(void);
3184 void Render_Init(void)
3196 R_LightningBeams_Init();
3205 extern char *ENGINE_EXTENSIONS;
3208 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3209 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3210 gl_version = (const char *)qglGetString(GL_VERSION);
3211 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3215 if (!gl_platformextensions)
3216 gl_platformextensions = "";
3218 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3219 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3220 Con_Printf("GL_VERSION: %s\n", gl_version);
3221 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3222 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3224 VID_CheckExtensions();
3226 // LordHavoc: report supported extensions
3227 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3229 // clear to black (loading plaque will be seen over this)
3231 qglClearColor(0,0,0,1);CHECKGLERROR
3232 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3235 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3239 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3241 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3244 p = r_refdef.view.frustum + i;
3249 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3253 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3257 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3261 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3265 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3269 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3273 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3277 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3285 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3289 for (i = 0;i < numplanes;i++)
3296 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3300 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3304 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3308 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3312 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3316 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3320 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3324 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3332 //==================================================================================
3334 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3337 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3338 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3339 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3342 typedef struct r_animcache_entity_s
3349 qboolean wantnormals;
3350 qboolean wanttangents;
3352 r_animcache_entity_t;
3354 typedef struct r_animcache_s
3356 r_animcache_entity_t entity[MAX_EDICTS];
3362 static r_animcache_t r_animcachestate;
3364 void R_AnimCache_Free(void)
3367 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3369 r_animcachestate.entity[idx].maxvertices = 0;
3370 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3371 r_animcachestate.entity[idx].vertex3f = NULL;
3372 r_animcachestate.entity[idx].normal3f = NULL;
3373 r_animcachestate.entity[idx].svector3f = NULL;
3374 r_animcachestate.entity[idx].tvector3f = NULL;
3376 r_animcachestate.currentindex = 0;
3377 r_animcachestate.maxindex = 0;
3380 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3384 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3386 if (cache->maxvertices >= numvertices)
3389 // Release existing memory
3390 if (cache->vertex3f)
3391 Mem_Free(cache->vertex3f);
3393 // Pad by 1024 verts
3394 cache->maxvertices = (numvertices + 1023) & ~1023;
3395 arraySize = cache->maxvertices * 3;
3397 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3398 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3399 r_animcachestate.entity[cacheIdx].vertex3f = base;
3400 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3401 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3402 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3404 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3407 void R_AnimCache_NewFrame(void)
3411 if (r_animcache.integer && r_drawentities.integer)
3412 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3413 else if (r_animcachestate.maxindex)
3416 r_animcachestate.currentindex = 0;
3418 for (i = 0;i < r_refdef.scene.numentities;i++)
3419 r_refdef.scene.entities[i]->animcacheindex = -1;
3422 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3424 dp_model_t *model = ent->model;
3425 r_animcache_entity_t *c;
3426 // see if it's already cached this frame
3427 if (ent->animcacheindex >= 0)
3429 // add normals/tangents if needed
3430 c = r_animcachestate.entity + ent->animcacheindex;
3432 wantnormals = false;
3433 if (c->wanttangents)
3434 wanttangents = false;
3435 if (wantnormals || wanttangents)
3436 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3440 // see if this ent is worth caching
3441 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3443 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3445 // assign it a cache entry and make sure the arrays are big enough
3446 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3447 ent->animcacheindex = r_animcachestate.currentindex++;
3448 c = r_animcachestate.entity + ent->animcacheindex;
3449 c->wantnormals = wantnormals;
3450 c->wanttangents = wanttangents;
3451 model->AnimateVertices(model, ent->frameblend, ent->skeleton, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3456 void R_AnimCache_CacheVisibleEntities(void)
3459 qboolean wantnormals;
3460 qboolean wanttangents;
3462 if (!r_animcachestate.maxindex)
3465 wantnormals = !r_showsurfaces.integer;
3466 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3468 // TODO: thread this?
3470 for (i = 0;i < r_refdef.scene.numentities;i++)
3472 if (!r_refdef.viewcache.entityvisible[i])
3474 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3478 //==================================================================================
3480 static void R_View_UpdateEntityLighting (void)
3483 entity_render_t *ent;
3484 vec3_t tempdiffusenormal, avg;
3485 vec_t f, fa, fd, fdd;
3487 for (i = 0;i < r_refdef.scene.numentities;i++)
3489 ent = r_refdef.scene.entities[i];
3491 // skip unseen models
3492 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3496 if (ent->model && ent->model->brush.num_leafs)
3498 // TODO: use modellight for r_ambient settings on world?
3499 VectorSet(ent->modellight_ambient, 0, 0, 0);
3500 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3501 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3505 // fetch the lighting from the worldmodel data
3506 VectorSet(ent->modellight_ambient, r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f));
3507 VectorClear(ent->modellight_diffuse);
3508 VectorClear(tempdiffusenormal);
3509 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3512 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3513 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3514 if(ent->flags & RENDER_EQUALIZE)
3516 // first fix up ambient lighting...
3517 if(r_equalize_entities_minambient.value > 0)
3519 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3522 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3523 if(fa < r_equalize_entities_minambient.value * fd)
3526 // fa'/fd' = minambient
3527 // fa'+0.25*fd' = fa+0.25*fd
3529 // fa' = fd' * minambient
3530 // fd'*(0.25+minambient) = fa+0.25*fd
3532 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3533 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3535 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3536 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
3537 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3538 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3543 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3545 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3546 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3549 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3550 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3551 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3557 VectorSet(ent->modellight_ambient, 1, 1, 1);
3559 // move the light direction into modelspace coordinates for lighting code
3560 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3561 if(VectorLength2(ent->modellight_lightdir) == 0)
3562 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3563 VectorNormalize(ent->modellight_lightdir);
3567 #define MAX_LINEOFSIGHTTRACES 64
3569 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3572 vec3_t boxmins, boxmaxs;
3575 dp_model_t *model = r_refdef.scene.worldmodel;
3577 if (!model || !model->brush.TraceLineOfSight)
3580 // expand the box a little
3581 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3582 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3583 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3584 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3585 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3586 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3589 VectorCopy(eye, start);
3590 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3591 if (model->brush.TraceLineOfSight(model, start, end))
3594 // try various random positions
3595 for (i = 0;i < numsamples;i++)
3597 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3598 if (model->brush.TraceLineOfSight(model, start, end))
3606 static void R_View_UpdateEntityVisible (void)
3611 entity_render_t *ent;
3613 if (!r_drawentities.integer)
3616 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3617 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3619 // worldmodel can check visibility
3620 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3621 for (i = 0;i < r_refdef.scene.numentities;i++)
3623 ent = r_refdef.scene.entities[i];
3624 if (!(ent->flags & renderimask))
3625 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)))
3626 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))
3627 r_refdef.viewcache.entityvisible[i] = true;
3629 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3631 for (i = 0;i < r_refdef.scene.numentities;i++)
3633 ent = r_refdef.scene.entities[i];
3634 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3636 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3638 continue; // temp entities do pvs only
3639 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3640 ent->last_trace_visibility = realtime;
3641 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3642 r_refdef.viewcache.entityvisible[i] = 0;
3649 // no worldmodel or it can't check visibility
3650 for (i = 0;i < r_refdef.scene.numentities;i++)
3652 ent = r_refdef.scene.entities[i];
3653 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));
3658 /// only used if skyrendermasked, and normally returns false
3659 int R_DrawBrushModelsSky (void)
3662 entity_render_t *ent;
3664 if (!r_drawentities.integer)
3668 for (i = 0;i < r_refdef.scene.numentities;i++)
3670 if (!r_refdef.viewcache.entityvisible[i])
3672 ent = r_refdef.scene.entities[i];
3673 if (!ent->model || !ent->model->DrawSky)
3675 ent->model->DrawSky(ent);
3681 static void R_DrawNoModel(entity_render_t *ent);
3682 static void R_DrawModels(void)
3685 entity_render_t *ent;
3687 if (!r_drawentities.integer)
3690 for (i = 0;i < r_refdef.scene.numentities;i++)
3692 if (!r_refdef.viewcache.entityvisible[i])
3694 ent = r_refdef.scene.entities[i];
3695 r_refdef.stats.entities++;
3696 if (ent->model && ent->model->Draw != NULL)
3697 ent->model->Draw(ent);
3703 static void R_DrawModelsDepth(void)
3706 entity_render_t *ent;
3708 if (!r_drawentities.integer)
3711 for (i = 0;i < r_refdef.scene.numentities;i++)
3713 if (!r_refdef.viewcache.entityvisible[i])
3715 ent = r_refdef.scene.entities[i];
3716 if (ent->model && ent->model->DrawDepth != NULL)
3717 ent->model->DrawDepth(ent);
3721 static void R_DrawModelsDebug(void)
3724 entity_render_t *ent;
3726 if (!r_drawentities.integer)
3729 for (i = 0;i < r_refdef.scene.numentities;i++)
3731 if (!r_refdef.viewcache.entityvisible[i])
3733 ent = r_refdef.scene.entities[i];
3734 if (ent->model && ent->model->DrawDebug != NULL)
3735 ent->model->DrawDebug(ent);
3739 static void R_DrawModelsAddWaterPlanes(void)
3742 entity_render_t *ent;
3744 if (!r_drawentities.integer)
3747 for (i = 0;i < r_refdef.scene.numentities;i++)
3749 if (!r_refdef.viewcache.entityvisible[i])
3751 ent = r_refdef.scene.entities[i];
3752 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3753 ent->model->DrawAddWaterPlanes(ent);
3757 static void R_View_SetFrustum(void)
3760 double slopex, slopey;
3761 vec3_t forward, left, up, origin;
3763 // we can't trust r_refdef.view.forward and friends in reflected scenes
3764 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3767 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3768 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3769 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3770 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3771 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3772 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3773 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3774 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3775 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3776 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3777 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3778 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3782 zNear = r_refdef.nearclip;
3783 nudge = 1.0 - 1.0 / (1<<23);
3784 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3785 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3786 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3787 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3788 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3789 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3790 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3791 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3797 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3798 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3799 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3800 r_refdef.view.frustum[0].dist = m[15] - m[12];
3802 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3803 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3804 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3805 r_refdef.view.frustum[1].dist = m[15] + m[12];
3807 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3808 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3809 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3810 r_refdef.view.frustum[2].dist = m[15] - m[13];
3812 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3813 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3814 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3815 r_refdef.view.frustum[3].dist = m[15] + m[13];
3817 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3818 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3819 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3820 r_refdef.view.frustum[4].dist = m[15] - m[14];
3822 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3823 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3824 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3825 r_refdef.view.frustum[5].dist = m[15] + m[14];
3828 if (r_refdef.view.useperspective)
3830 slopex = 1.0 / r_refdef.view.frustum_x;
3831 slopey = 1.0 / r_refdef.view.frustum_y;
3832 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3833 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3834 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3835 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3836 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3838 // Leaving those out was a mistake, those were in the old code, and they
3839 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3840 // I couldn't reproduce it after adding those normalizations. --blub
3841 VectorNormalize(r_refdef.view.frustum[0].normal);
3842 VectorNormalize(r_refdef.view.frustum[1].normal);
3843 VectorNormalize(r_refdef.view.frustum[2].normal);
3844 VectorNormalize(r_refdef.view.frustum[3].normal);
3846 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3847 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]);
3848 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]);
3849 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]);
3850 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]);
3852 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3853 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3854 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3855 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3856 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3860 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3861 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3862 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3863 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3864 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3865 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3866 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3867 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3868 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3869 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3871 r_refdef.view.numfrustumplanes = 5;
3873 if (r_refdef.view.useclipplane)
3875 r_refdef.view.numfrustumplanes = 6;
3876 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3879 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3880 PlaneClassify(r_refdef.view.frustum + i);
3882 // LordHavoc: note to all quake engine coders, Quake had a special case
3883 // for 90 degrees which assumed a square view (wrong), so I removed it,
3884 // Quake2 has it disabled as well.
3886 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3887 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3888 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3889 //PlaneClassify(&frustum[0]);
3891 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3892 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3893 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3894 //PlaneClassify(&frustum[1]);
3896 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3897 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3898 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3899 //PlaneClassify(&frustum[2]);
3901 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3902 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3903 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3904 //PlaneClassify(&frustum[3]);
3907 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3908 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3909 //PlaneClassify(&frustum[4]);
3912 void R_View_Update(void)
3914 R_Main_ResizeViewCache();
3915 R_View_SetFrustum();
3916 R_View_WorldVisibility(r_refdef.view.useclipplane);
3917 R_View_UpdateEntityVisible();
3918 R_View_UpdateEntityLighting();
3921 void R_SetupView(qboolean allowwaterclippingplane)
3923 const double *customclipplane = NULL;
3925 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3927 // LordHavoc: couldn't figure out how to make this approach the
3928 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3929 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3930 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3931 dist = r_refdef.view.clipplane.dist;
3932 plane[0] = r_refdef.view.clipplane.normal[0];
3933 plane[1] = r_refdef.view.clipplane.normal[1];
3934 plane[2] = r_refdef.view.clipplane.normal[2];
3936 customclipplane = plane;
3939 if (!r_refdef.view.useperspective)
3940 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);
3941 else if (vid.stencil && r_useinfinitefarclip.integer)
3942 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);
3944 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);
3945 R_SetViewport(&r_refdef.view.viewport);
3948 void R_ResetViewRendering2D(void)
3950 r_viewport_t viewport;
3953 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3954 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);
3955 R_SetViewport(&viewport);
3956 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3957 GL_Color(1, 1, 1, 1);
3958 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3959 GL_BlendFunc(GL_ONE, GL_ZERO);
3960 GL_AlphaTest(false);
3961 GL_ScissorTest(false);
3962 GL_DepthMask(false);
3963 GL_DepthRange(0, 1);
3964 GL_DepthTest(false);
3965 R_Mesh_Matrix(&identitymatrix);
3966 R_Mesh_ResetTextureState();
3967 GL_PolygonOffset(0, 0);
3968 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3969 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3970 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3971 qglStencilMask(~0);CHECKGLERROR
3972 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3973 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3974 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3975 R_SetupGenericShader(true);
3978 void R_ResetViewRendering3D(void)
3983 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3984 GL_Color(1, 1, 1, 1);
3985 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3986 GL_BlendFunc(GL_ONE, GL_ZERO);
3987 GL_AlphaTest(false);
3988 GL_ScissorTest(true);
3990 GL_DepthRange(0, 1);
3992 R_Mesh_Matrix(&identitymatrix);
3993 R_Mesh_ResetTextureState();
3994 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3995 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3996 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3997 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3998 qglStencilMask(~0);CHECKGLERROR
3999 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4000 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4001 GL_CullFace(r_refdef.view.cullface_back);
4002 R_SetupGenericShader(true);
4005 void R_RenderScene(void);
4006 void R_RenderWaterPlanes(void);
4008 static void R_Water_StartFrame(void)
4011 int waterwidth, waterheight, texturewidth, textureheight;
4012 r_waterstate_waterplane_t *p;
4014 // set waterwidth and waterheight to the water resolution that will be
4015 // used (often less than the screen resolution for faster rendering)
4016 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
4017 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
4019 // calculate desired texture sizes
4020 // can't use water if the card does not support the texture size
4021 if (!r_water.integer || !r_glsl.integer || !vid.support.arb_fragment_shader || waterwidth > (int)vid.maxtexturesize_2d || waterheight > (int)vid.maxtexturesize_2d || r_showsurfaces.integer)
4022 texturewidth = textureheight = waterwidth = waterheight = 0;
4023 else if (vid.support.arb_texture_non_power_of_two)
4025 texturewidth = waterwidth;
4026 textureheight = waterheight;
4030 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4031 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4034 // allocate textures as needed
4035 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4037 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4038 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4040 if (p->texture_refraction)
4041 R_FreeTexture(p->texture_refraction);
4042 p->texture_refraction = NULL;
4043 if (p->texture_reflection)
4044 R_FreeTexture(p->texture_reflection);
4045 p->texture_reflection = NULL;
4047 memset(&r_waterstate, 0, sizeof(r_waterstate));
4048 r_waterstate.texturewidth = texturewidth;
4049 r_waterstate.textureheight = textureheight;
4052 if (r_waterstate.texturewidth)
4054 r_waterstate.enabled = true;
4056 // when doing a reduced render (HDR) we want to use a smaller area
4057 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4058 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4060 // set up variables that will be used in shader setup
4061 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4062 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4063 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4064 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4067 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4068 r_waterstate.numwaterplanes = 0;
4071 void R_Water_AddWaterPlane(msurface_t *surface)
4073 int triangleindex, planeindex;
4079 r_waterstate_waterplane_t *p;
4080 texture_t *t = R_GetCurrentTexture(surface->texture);
4081 // just use the first triangle with a valid normal for any decisions
4082 VectorClear(normal);
4083 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4085 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4086 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4087 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4088 TriangleNormal(vert[0], vert[1], vert[2], normal);
4089 if (VectorLength2(normal) >= 0.001)
4093 VectorCopy(normal, plane.normal);
4094 VectorNormalize(plane.normal);
4095 plane.dist = DotProduct(vert[0], plane.normal);
4096 PlaneClassify(&plane);
4097 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4099 // skip backfaces (except if nocullface is set)
4100 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4102 VectorNegate(plane.normal, plane.normal);
4104 PlaneClassify(&plane);
4108 // find a matching plane if there is one
4109 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4110 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4112 if (planeindex >= r_waterstate.maxwaterplanes)
4113 return; // nothing we can do, out of planes
4115 // if this triangle does not fit any known plane rendered this frame, add one
4116 if (planeindex >= r_waterstate.numwaterplanes)
4118 // store the new plane
4119 r_waterstate.numwaterplanes++;
4121 // clear materialflags and pvs
4122 p->materialflags = 0;
4123 p->pvsvalid = false;
4125 // merge this surface's materialflags into the waterplane
4126 p->materialflags |= t->currentmaterialflags;
4127 // merge this surface's PVS into the waterplane
4128 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4129 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4130 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4132 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4137 static void R_Water_ProcessPlanes(void)
4139 r_refdef_view_t originalview;
4140 r_refdef_view_t myview;
4142 r_waterstate_waterplane_t *p;
4144 originalview = r_refdef.view;
4146 // make sure enough textures are allocated
4147 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4149 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4151 if (!p->texture_refraction)
4152 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);
4153 if (!p->texture_refraction)
4157 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4159 if (!p->texture_reflection)
4160 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);
4161 if (!p->texture_reflection)
4167 r_refdef.view = originalview;
4168 r_refdef.view.showdebug = false;
4169 r_refdef.view.width = r_waterstate.waterwidth;
4170 r_refdef.view.height = r_waterstate.waterheight;
4171 r_refdef.view.useclipplane = true;
4172 myview = r_refdef.view;
4173 r_waterstate.renderingscene = true;
4174 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4176 // render the normal view scene and copy into texture
4177 // (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)
4178 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4180 r_refdef.view = myview;
4181 r_refdef.view.clipplane = p->plane;
4182 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4183 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4184 PlaneClassify(&r_refdef.view.clipplane);
4186 R_ResetViewRendering3D();
4187 R_ClearScreen(r_refdef.fogenabled);
4191 // copy view into the screen texture
4192 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4193 GL_ActiveTexture(0);
4195 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
4198 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4200 r_refdef.view = myview;
4201 // render reflected scene and copy into texture
4202 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4203 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4204 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4205 r_refdef.view.clipplane = p->plane;
4206 // reverse the cullface settings for this render
4207 r_refdef.view.cullface_front = GL_FRONT;
4208 r_refdef.view.cullface_back = GL_BACK;
4209 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4211 r_refdef.view.usecustompvs = true;
4213 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4215 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4218 R_ResetViewRendering3D();
4219 R_ClearScreen(r_refdef.fogenabled);
4223 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4224 GL_ActiveTexture(0);
4226 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
4229 r_waterstate.renderingscene = false;
4230 r_refdef.view = originalview;
4231 R_ResetViewRendering3D();
4232 R_ClearScreen(r_refdef.fogenabled);
4236 r_refdef.view = originalview;
4237 r_waterstate.renderingscene = false;
4238 Cvar_SetValueQuick(&r_water, 0);
4239 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4243 void R_Bloom_StartFrame(void)
4245 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4247 // set bloomwidth and bloomheight to the bloom resolution that will be
4248 // used (often less than the screen resolution for faster rendering)
4249 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4250 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4251 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4252 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
4253 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
4255 // calculate desired texture sizes
4256 if (vid.support.arb_texture_non_power_of_two)
4258 screentexturewidth = r_refdef.view.width;
4259 screentextureheight = r_refdef.view.height;
4260 bloomtexturewidth = r_bloomstate.bloomwidth;
4261 bloomtextureheight = r_bloomstate.bloomheight;
4265 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4266 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4267 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4268 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4271 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))
4273 Cvar_SetValueQuick(&r_hdr, 0);
4274 Cvar_SetValueQuick(&r_bloom, 0);
4275 Cvar_SetValueQuick(&r_motionblur, 0);
4276 Cvar_SetValueQuick(&r_damageblur, 0);
4279 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
4280 screentexturewidth = screentextureheight = 0;
4281 if (!r_hdr.integer && !r_bloom.integer)
4282 bloomtexturewidth = bloomtextureheight = 0;
4284 // allocate textures as needed
4285 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4287 if (r_bloomstate.texture_screen)
4288 R_FreeTexture(r_bloomstate.texture_screen);
4289 r_bloomstate.texture_screen = NULL;
4290 r_bloomstate.screentexturewidth = screentexturewidth;
4291 r_bloomstate.screentextureheight = screentextureheight;
4292 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4293 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);
4295 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4297 if (r_bloomstate.texture_bloom)
4298 R_FreeTexture(r_bloomstate.texture_bloom);
4299 r_bloomstate.texture_bloom = NULL;
4300 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4301 r_bloomstate.bloomtextureheight = bloomtextureheight;
4302 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4303 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);
4306 // when doing a reduced render (HDR) we want to use a smaller area
4307 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4308 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4309 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4310 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4311 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4313 // set up a texcoord array for the full resolution screen image
4314 // (we have to keep this around to copy back during final render)
4315 r_bloomstate.screentexcoord2f[0] = 0;
4316 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4317 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4318 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4319 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4320 r_bloomstate.screentexcoord2f[5] = 0;
4321 r_bloomstate.screentexcoord2f[6] = 0;
4322 r_bloomstate.screentexcoord2f[7] = 0;
4324 // set up a texcoord array for the reduced resolution bloom image
4325 // (which will be additive blended over the screen image)
4326 r_bloomstate.bloomtexcoord2f[0] = 0;
4327 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4328 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4329 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4330 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4331 r_bloomstate.bloomtexcoord2f[5] = 0;
4332 r_bloomstate.bloomtexcoord2f[6] = 0;
4333 r_bloomstate.bloomtexcoord2f[7] = 0;
4335 if (r_hdr.integer || r_bloom.integer)
4337 r_bloomstate.enabled = true;
4338 r_bloomstate.hdr = r_hdr.integer != 0;
4341 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);
4344 void R_Bloom_CopyBloomTexture(float colorscale)
4346 r_refdef.stats.bloom++;
4348 // scale down screen texture to the bloom texture size
4350 R_SetViewport(&r_bloomstate.viewport);
4351 GL_BlendFunc(GL_ONE, GL_ZERO);
4352 GL_Color(colorscale, colorscale, colorscale, 1);
4353 // TODO: optimize with multitexture or GLSL
4354 R_SetupGenericShader(true);
4355 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4356 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4357 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4358 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4360 // we now have a bloom image in the framebuffer
4361 // copy it into the bloom image texture for later processing
4362 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4363 GL_ActiveTexture(0);
4365 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4366 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4369 void R_Bloom_CopyHDRTexture(void)
4371 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4372 GL_ActiveTexture(0);
4374 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
4375 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4378 void R_Bloom_MakeTexture(void)
4381 float xoffset, yoffset, r, brighten;
4383 r_refdef.stats.bloom++;
4385 R_ResetViewRendering2D();
4386 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4387 R_Mesh_ColorPointer(NULL, 0, 0);
4388 R_SetupGenericShader(true);
4390 // we have a bloom image in the framebuffer
4392 R_SetViewport(&r_bloomstate.viewport);
4394 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4397 r = bound(0, r_bloom_colorexponent.value / x, 1);
4398 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4399 GL_Color(r, r, r, 1);
4400 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4401 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4402 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4403 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4405 // copy the vertically blurred bloom view to a texture
4406 GL_ActiveTexture(0);
4408 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4409 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4412 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4413 brighten = r_bloom_brighten.value;
4415 brighten *= r_hdr_range.value;
4416 brighten = sqrt(brighten);
4418 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4419 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4420 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4422 for (dir = 0;dir < 2;dir++)
4424 // blend on at multiple vertical offsets to achieve a vertical blur
4425 // TODO: do offset blends using GLSL
4426 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4427 GL_BlendFunc(GL_ONE, GL_ZERO);
4428 for (x = -range;x <= range;x++)
4430 if (!dir){xoffset = 0;yoffset = x;}
4431 else {xoffset = x;yoffset = 0;}
4432 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4433 yoffset /= (float)r_bloomstate.bloomtextureheight;
4434 // compute a texcoord array with the specified x and y offset
4435 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4436 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4437 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4438 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4439 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4440 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4441 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4442 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4443 // this r value looks like a 'dot' particle, fading sharply to
4444 // black at the edges
4445 // (probably not realistic but looks good enough)
4446 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4447 //r = brighten/(range*2+1);
4448 r = brighten / (range * 2 + 1);
4450 r *= (1 - x*x/(float)(range*range));
4451 GL_Color(r, r, r, 1);
4452 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4453 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4454 GL_BlendFunc(GL_ONE, GL_ONE);
4457 // copy the vertically blurred bloom view to a texture
4458 GL_ActiveTexture(0);
4460 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4461 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4464 // apply subtract last
4465 // (just like it would be in a GLSL shader)
4466 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
4468 GL_BlendFunc(GL_ONE, GL_ZERO);
4469 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4470 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4471 GL_Color(1, 1, 1, 1);
4472 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4473 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4475 GL_BlendFunc(GL_ONE, GL_ONE);
4476 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4477 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4478 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4479 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4480 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4481 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4482 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4484 // copy the darkened bloom view to a texture
4485 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4486 GL_ActiveTexture(0);
4488 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4489 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4493 void R_HDR_RenderBloomTexture(void)
4495 int oldwidth, oldheight;
4496 float oldcolorscale;
4498 oldcolorscale = r_refdef.view.colorscale;
4499 oldwidth = r_refdef.view.width;
4500 oldheight = r_refdef.view.height;
4501 r_refdef.view.width = r_bloomstate.bloomwidth;
4502 r_refdef.view.height = r_bloomstate.bloomheight;
4504 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4505 // TODO: add exposure compensation features
4506 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4508 r_refdef.view.showdebug = false;
4509 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4511 R_ResetViewRendering3D();
4513 R_ClearScreen(r_refdef.fogenabled);
4514 if (r_timereport_active)
4515 R_TimeReport("HDRclear");
4518 if (r_timereport_active)
4519 R_TimeReport("visibility");
4521 // only do secondary renders with HDR if r_hdr is 2 or higher
4522 r_waterstate.numwaterplanes = 0;
4523 if (r_waterstate.enabled && r_hdr.integer >= 2)
4524 R_RenderWaterPlanes();
4526 r_refdef.view.showdebug = true;
4528 r_waterstate.numwaterplanes = 0;
4530 R_ResetViewRendering2D();
4532 R_Bloom_CopyHDRTexture();
4533 R_Bloom_MakeTexture();
4535 // restore the view settings
4536 r_refdef.view.width = oldwidth;
4537 r_refdef.view.height = oldheight;
4538 r_refdef.view.colorscale = oldcolorscale;
4540 R_ResetViewRendering3D();
4542 R_ClearScreen(r_refdef.fogenabled);
4543 if (r_timereport_active)
4544 R_TimeReport("viewclear");
4547 static void R_BlendView(void)
4549 if (r_bloomstate.texture_screen)
4551 // make sure the buffer is available
4552 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4554 R_ResetViewRendering2D();
4555 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4556 R_Mesh_ColorPointer(NULL, 0, 0);
4557 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4558 GL_ActiveTexture(0);CHECKGLERROR
4560 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4562 // declare variables
4564 static float avgspeed;
4566 speed = VectorLength(cl.movement_velocity);
4568 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4569 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4571 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4572 speed = bound(0, speed, 1);
4573 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4575 // calculate values into a standard alpha
4576 cl.motionbluralpha = 1 - exp(-
4578 (r_motionblur.value * speed / 80)
4580 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4583 max(0.0001, cl.time - cl.oldtime) // fps independent
4586 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4587 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4589 if (cl.motionbluralpha > 0)
4591 R_SetupGenericShader(true);
4592 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4593 GL_Color(1, 1, 1, cl.motionbluralpha);
4594 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4595 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4596 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4597 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4601 // copy view into the screen texture
4602 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
4603 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4606 if (r_glsl.integer && vid.support.arb_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4608 unsigned int permutation =
4609 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4610 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4611 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4612 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4613 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4615 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4617 // render simple bloom effect
4618 // copy the screen and shrink it and darken it for the bloom process
4619 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4620 // make the bloom texture
4621 R_Bloom_MakeTexture();
4624 R_ResetViewRendering2D();
4625 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4626 R_Mesh_ColorPointer(NULL, 0, 0);
4627 GL_Color(1, 1, 1, 1);
4628 GL_BlendFunc(GL_ONE, GL_ZERO);
4629 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4630 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4631 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4632 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4633 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4634 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4635 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4636 if (r_glsl_permutation->loc_TintColor >= 0)
4637 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4638 if (r_glsl_permutation->loc_ClientTime >= 0)
4639 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4640 if (r_glsl_permutation->loc_PixelSize >= 0)
4641 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4642 if (r_glsl_permutation->loc_UserVec1 >= 0)
4644 float a=0, b=0, c=0, d=0;
4645 #if _MSC_VER >= 1400
4646 #define sscanf sscanf_s
4648 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4649 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4651 if (r_glsl_permutation->loc_UserVec2 >= 0)
4653 float a=0, b=0, c=0, d=0;
4654 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4655 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4657 if (r_glsl_permutation->loc_UserVec3 >= 0)
4659 float a=0, b=0, c=0, d=0;
4660 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4661 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4663 if (r_glsl_permutation->loc_UserVec4 >= 0)
4665 float a=0, b=0, c=0, d=0;
4666 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4667 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4669 if (r_glsl_permutation->loc_Saturation >= 0)
4670 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4671 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4672 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4678 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4680 // render high dynamic range bloom effect
4681 // the bloom texture was made earlier this render, so we just need to
4682 // blend it onto the screen...
4683 R_ResetViewRendering2D();
4684 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4685 R_Mesh_ColorPointer(NULL, 0, 0);
4686 R_SetupGenericShader(true);
4687 GL_Color(1, 1, 1, 1);
4688 GL_BlendFunc(GL_ONE, GL_ONE);
4689 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4690 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4691 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4692 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4694 else if (r_bloomstate.texture_bloom)
4696 // render simple bloom effect
4697 // copy the screen and shrink it and darken it for the bloom process
4698 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4699 // make the bloom texture
4700 R_Bloom_MakeTexture();
4701 // put the original screen image back in place and blend the bloom
4703 R_ResetViewRendering2D();
4704 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4705 R_Mesh_ColorPointer(NULL, 0, 0);
4706 GL_Color(1, 1, 1, 1);
4707 GL_BlendFunc(GL_ONE, GL_ZERO);
4708 // do both in one pass if possible
4709 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4710 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4711 if (r_textureunits.integer >= 2 && gl_combine.integer)
4713 R_SetupGenericTwoTextureShader(GL_ADD);
4714 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4715 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4719 R_SetupGenericShader(true);
4720 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4721 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4722 // now blend on the bloom texture
4723 GL_BlendFunc(GL_ONE, GL_ONE);
4724 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4725 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4727 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4728 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4730 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4732 // apply a color tint to the whole view
4733 R_ResetViewRendering2D();
4734 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4735 R_Mesh_ColorPointer(NULL, 0, 0);
4736 R_SetupGenericShader(false);
4737 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4738 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4739 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4743 matrix4x4_t r_waterscrollmatrix;
4745 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4747 if (r_refdef.fog_density)
4749 r_refdef.fogcolor[0] = r_refdef.fog_red;
4750 r_refdef.fogcolor[1] = r_refdef.fog_green;
4751 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4753 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4754 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4755 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4756 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4760 VectorCopy(r_refdef.fogcolor, fogvec);
4761 // color.rgb *= ContrastBoost * SceneBrightness;
4762 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4763 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4764 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4765 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4770 void R_UpdateVariables(void)
4774 r_refdef.scene.ambient = r_ambient.value;
4776 r_refdef.farclip = r_farclip_base.value;
4777 if (r_refdef.scene.worldmodel)
4778 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
4779 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4781 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4782 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4783 r_refdef.polygonfactor = 0;
4784 r_refdef.polygonoffset = 0;
4785 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4786 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4788 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4789 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
4790 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4791 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
4792 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4793 if (r_showsurfaces.integer)
4795 r_refdef.scene.rtworld = false;
4796 r_refdef.scene.rtworldshadows = false;
4797 r_refdef.scene.rtdlight = false;
4798 r_refdef.scene.rtdlightshadows = false;
4799 r_refdef.lightmapintensity = 0;
4802 if (gamemode == GAME_NEHAHRA)
4804 if (gl_fogenable.integer)
4806 r_refdef.oldgl_fogenable = true;
4807 r_refdef.fog_density = gl_fogdensity.value;
4808 r_refdef.fog_red = gl_fogred.value;
4809 r_refdef.fog_green = gl_foggreen.value;
4810 r_refdef.fog_blue = gl_fogblue.value;
4811 r_refdef.fog_alpha = 1;
4812 r_refdef.fog_start = 0;
4813 r_refdef.fog_end = gl_skyclip.value;
4814 r_refdef.fog_height = 1<<30;
4815 r_refdef.fog_fadedepth = 128;
4817 else if (r_refdef.oldgl_fogenable)
4819 r_refdef.oldgl_fogenable = false;
4820 r_refdef.fog_density = 0;
4821 r_refdef.fog_red = 0;
4822 r_refdef.fog_green = 0;
4823 r_refdef.fog_blue = 0;
4824 r_refdef.fog_alpha = 0;
4825 r_refdef.fog_start = 0;
4826 r_refdef.fog_end = 0;
4827 r_refdef.fog_height = 1<<30;
4828 r_refdef.fog_fadedepth = 128;
4832 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4833 r_refdef.fog_start = max(0, r_refdef.fog_start);
4834 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4836 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4838 if (r_refdef.fog_density && r_drawfog.integer)
4840 r_refdef.fogenabled = true;
4841 // this is the point where the fog reaches 0.9986 alpha, which we
4842 // consider a good enough cutoff point for the texture
4843 // (0.9986 * 256 == 255.6)
4844 if (r_fog_exp2.integer)
4845 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4847 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4848 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4849 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4850 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4851 // fog color was already set
4852 // update the fog texture
4853 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)
4854 R_BuildFogTexture();
4857 r_refdef.fogenabled = false;
4859 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4861 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4863 // build GLSL gamma texture
4864 #define RAMPWIDTH 256
4865 unsigned short ramp[RAMPWIDTH * 3];
4866 unsigned char rampbgr[RAMPWIDTH][4];
4869 r_texture_gammaramps_serial = vid_gammatables_serial;
4871 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4872 for(i = 0; i < RAMPWIDTH; ++i)
4874 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4875 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4876 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4879 if (r_texture_gammaramps)
4881 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4885 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);
4891 // remove GLSL gamma texture
4895 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4896 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4902 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4903 if( scenetype != r_currentscenetype ) {
4904 // store the old scenetype
4905 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4906 r_currentscenetype = scenetype;
4907 // move in the new scene
4908 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4917 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4919 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4920 if( scenetype == r_currentscenetype ) {
4921 return &r_refdef.scene;
4923 return &r_scenes_store[ scenetype ];
4932 void R_RenderView(void)
4934 if (r_timereport_active)
4935 R_TimeReport("start");
4936 r_frame++; // used only by R_GetCurrentTexture
4937 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4939 R_AnimCache_NewFrame();
4941 if (r_refdef.view.isoverlay)
4943 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4944 GL_Clear( GL_DEPTH_BUFFER_BIT );
4945 R_TimeReport("depthclear");
4947 r_refdef.view.showdebug = false;
4949 r_waterstate.enabled = false;
4950 r_waterstate.numwaterplanes = 0;
4958 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4959 return; //Host_Error ("R_RenderView: NULL worldmodel");
4961 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4963 // break apart the view matrix into vectors for various purposes
4964 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4965 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4966 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4967 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4968 // make an inverted copy of the view matrix for tracking sprites
4969 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4971 R_Shadow_UpdateWorldLightSelection();
4973 R_Bloom_StartFrame();
4974 R_Water_StartFrame();
4977 if (r_timereport_active)
4978 R_TimeReport("viewsetup");
4980 R_ResetViewRendering3D();
4982 if (r_refdef.view.clear || r_refdef.fogenabled)
4984 R_ClearScreen(r_refdef.fogenabled);
4985 if (r_timereport_active)
4986 R_TimeReport("viewclear");
4988 r_refdef.view.clear = true;
4990 // this produces a bloom texture to be used in R_BlendView() later
4991 if (r_hdr.integer && r_bloomstate.bloomwidth)
4992 R_HDR_RenderBloomTexture();
4994 r_refdef.view.showdebug = true;
4997 if (r_timereport_active)
4998 R_TimeReport("visibility");
5000 r_waterstate.numwaterplanes = 0;
5001 if (r_waterstate.enabled)
5002 R_RenderWaterPlanes();
5005 r_waterstate.numwaterplanes = 0;
5008 if (r_timereport_active)
5009 R_TimeReport("blendview");
5011 GL_Scissor(0, 0, vid.width, vid.height);
5012 GL_ScissorTest(false);
5016 void R_RenderWaterPlanes(void)
5018 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5020 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5021 if (r_timereport_active)
5022 R_TimeReport("waterworld");
5025 // don't let sound skip if going slow
5026 if (r_refdef.scene.extraupdate)
5029 R_DrawModelsAddWaterPlanes();
5030 if (r_timereport_active)
5031 R_TimeReport("watermodels");
5033 if (r_waterstate.numwaterplanes)
5035 R_Water_ProcessPlanes();
5036 if (r_timereport_active)
5037 R_TimeReport("waterscenes");
5041 extern void R_DrawLightningBeams (void);
5042 extern void VM_CL_AddPolygonsToMeshQueue (void);
5043 extern void R_DrawPortals (void);
5044 extern cvar_t cl_locs_show;
5045 static void R_DrawLocs(void);
5046 static void R_DrawEntityBBoxes(void);
5047 static void R_DrawModelDecals(void);
5048 extern cvar_t cl_decals_newsystem;
5049 void R_RenderScene(void)
5051 r_refdef.stats.renders++;
5055 // don't let sound skip if going slow
5056 if (r_refdef.scene.extraupdate)
5059 R_MeshQueue_BeginScene();
5063 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);
5065 if (cl.csqc_vidvars.drawworld)
5067 // don't let sound skip if going slow
5068 if (r_refdef.scene.extraupdate)
5071 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5073 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5074 if (r_timereport_active)
5075 R_TimeReport("worldsky");
5078 if (R_DrawBrushModelsSky() && r_timereport_active)
5079 R_TimeReport("bmodelsky");
5081 if (skyrendermasked && skyrenderlater)
5083 // we have to force off the water clipping plane while rendering sky
5090 R_AnimCache_CacheVisibleEntities();
5092 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5094 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5095 if (r_timereport_active)
5096 R_TimeReport("worlddepth");
5098 if (r_depthfirst.integer >= 2)
5100 R_DrawModelsDepth();
5101 if (r_timereport_active)
5102 R_TimeReport("modeldepth");
5105 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5107 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5108 if (r_timereport_active)
5109 R_TimeReport("world");
5112 // don't let sound skip if going slow
5113 if (r_refdef.scene.extraupdate)
5117 if (r_timereport_active)
5118 R_TimeReport("models");
5120 // don't let sound skip if going slow
5121 if (r_refdef.scene.extraupdate)
5124 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5126 R_DrawModelShadows();
5127 R_ResetViewRendering3D();
5128 // don't let sound skip if going slow
5129 if (r_refdef.scene.extraupdate)
5133 R_ShadowVolumeLighting(false);
5134 if (r_timereport_active)
5135 R_TimeReport("rtlights");
5137 // don't let sound skip if going slow
5138 if (r_refdef.scene.extraupdate)
5141 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5143 R_DrawModelShadows();
5144 R_ResetViewRendering3D();
5145 // don't let sound skip if going slow
5146 if (r_refdef.scene.extraupdate)
5150 if (cl.csqc_vidvars.drawworld)
5152 if (cl_decals_newsystem.integer)
5154 R_DrawModelDecals();
5155 if (r_timereport_active)
5156 R_TimeReport("modeldecals");
5161 if (r_timereport_active)
5162 R_TimeReport("decals");
5166 if (r_timereport_active)
5167 R_TimeReport("particles");
5170 if (r_timereport_active)
5171 R_TimeReport("explosions");
5173 R_DrawLightningBeams();
5174 if (r_timereport_active)
5175 R_TimeReport("lightning");
5178 R_SetupGenericShader(true);
5179 VM_CL_AddPolygonsToMeshQueue();
5181 if (r_refdef.view.showdebug)
5183 if (cl_locs_show.integer)
5186 if (r_timereport_active)
5187 R_TimeReport("showlocs");
5190 if (r_drawportals.integer)
5193 if (r_timereport_active)
5194 R_TimeReport("portals");
5197 if (r_showbboxes.value > 0)
5199 R_DrawEntityBBoxes();
5200 if (r_timereport_active)
5201 R_TimeReport("bboxes");
5205 R_SetupGenericShader(true);
5206 R_MeshQueue_RenderTransparent();
5207 if (r_timereport_active)
5208 R_TimeReport("drawtrans");
5210 R_SetupGenericShader(true);
5212 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))
5214 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5215 if (r_timereport_active)
5216 R_TimeReport("worlddebug");
5217 R_DrawModelsDebug();
5218 if (r_timereport_active)
5219 R_TimeReport("modeldebug");
5222 R_SetupGenericShader(true);
5224 if (cl.csqc_vidvars.drawworld)
5227 if (r_timereport_active)
5228 R_TimeReport("coronas");
5231 // don't let sound skip if going slow
5232 if (r_refdef.scene.extraupdate)
5235 R_ResetViewRendering2D();
5238 static const unsigned short bboxelements[36] =
5248 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5251 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5253 RSurf_ActiveWorldEntity();
5255 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5256 GL_DepthMask(false);
5257 GL_DepthRange(0, 1);
5258 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5259 R_Mesh_ResetTextureState();
5261 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5262 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5263 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5264 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5265 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5266 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5267 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5268 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5269 R_FillColors(color4f, 8, cr, cg, cb, ca);
5270 if (r_refdef.fogenabled)
5272 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5274 f1 = RSurf_FogVertex(v);
5276 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5277 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5278 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5281 R_Mesh_VertexPointer(vertex3f, 0, 0);
5282 R_Mesh_ColorPointer(color4f, 0, 0);
5283 R_Mesh_ResetTextureState();
5284 R_SetupGenericShader(false);
5285 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5288 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5292 prvm_edict_t *edict;
5293 prvm_prog_t *prog_save = prog;
5295 // this function draws bounding boxes of server entities
5299 GL_CullFace(GL_NONE);
5300 R_SetupGenericShader(false);
5304 for (i = 0;i < numsurfaces;i++)
5306 edict = PRVM_EDICT_NUM(surfacelist[i]);
5307 switch ((int)edict->fields.server->solid)
5309 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5310 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5311 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5312 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5313 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5314 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5316 color[3] *= r_showbboxes.value;
5317 color[3] = bound(0, color[3], 1);
5318 GL_DepthTest(!r_showdisabledepthtest.integer);
5319 GL_CullFace(r_refdef.view.cullface_front);
5320 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5326 static void R_DrawEntityBBoxes(void)
5329 prvm_edict_t *edict;
5331 prvm_prog_t *prog_save = prog;
5333 // this function draws bounding boxes of server entities
5339 for (i = 0;i < prog->num_edicts;i++)
5341 edict = PRVM_EDICT_NUM(i);
5342 if (edict->priv.server->free)
5344 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5345 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5347 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5349 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5350 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5356 static const int nomodelelement3i[24] =
5368 static const unsigned short nomodelelement3s[24] =
5380 static const float nomodelvertex3f[6*3] =
5390 static const float nomodelcolor4f[6*4] =
5392 0.0f, 0.0f, 0.5f, 1.0f,
5393 0.0f, 0.0f, 0.5f, 1.0f,
5394 0.0f, 0.5f, 0.0f, 1.0f,
5395 0.0f, 0.5f, 0.0f, 1.0f,
5396 0.5f, 0.0f, 0.0f, 1.0f,
5397 0.5f, 0.0f, 0.0f, 1.0f
5400 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5406 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);
5408 // this is only called once per entity so numsurfaces is always 1, and
5409 // surfacelist is always {0}, so this code does not handle batches
5411 if (rsurface.ent_flags & RENDER_ADDITIVE)
5413 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5414 GL_DepthMask(false);
5416 else if (rsurface.ent_color[3] < 1)
5418 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5419 GL_DepthMask(false);
5423 GL_BlendFunc(GL_ONE, GL_ZERO);
5426 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5427 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5428 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5429 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5430 R_SetupGenericShader(false);
5431 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5432 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5433 R_Mesh_ColorPointer(color4f, 0, 0);
5434 for (i = 0, c = color4f;i < 6;i++, c += 4)
5436 c[0] *= rsurface.ent_color[0];
5437 c[1] *= rsurface.ent_color[1];
5438 c[2] *= rsurface.ent_color[2];
5439 c[3] *= rsurface.ent_color[3];
5441 if (r_refdef.fogenabled)
5443 for (i = 0, c = color4f;i < 6;i++, c += 4)
5445 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5447 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5448 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5449 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5452 R_Mesh_ResetTextureState();
5453 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5456 void R_DrawNoModel(entity_render_t *ent)
5459 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5460 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5461 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5463 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5466 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5468 vec3_t right1, right2, diff, normal;
5470 VectorSubtract (org2, org1, normal);
5472 // calculate 'right' vector for start
5473 VectorSubtract (r_refdef.view.origin, org1, diff);
5474 CrossProduct (normal, diff, right1);
5475 VectorNormalize (right1);
5477 // calculate 'right' vector for end
5478 VectorSubtract (r_refdef.view.origin, org2, diff);
5479 CrossProduct (normal, diff, right2);
5480 VectorNormalize (right2);
5482 vert[ 0] = org1[0] + width * right1[0];
5483 vert[ 1] = org1[1] + width * right1[1];
5484 vert[ 2] = org1[2] + width * right1[2];
5485 vert[ 3] = org1[0] - width * right1[0];
5486 vert[ 4] = org1[1] - width * right1[1];
5487 vert[ 5] = org1[2] - width * right1[2];
5488 vert[ 6] = org2[0] - width * right2[0];
5489 vert[ 7] = org2[1] - width * right2[1];
5490 vert[ 8] = org2[2] - width * right2[2];
5491 vert[ 9] = org2[0] + width * right2[0];
5492 vert[10] = org2[1] + width * right2[1];
5493 vert[11] = org2[2] + width * right2[2];
5496 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)
5498 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5499 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5500 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5501 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5502 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5503 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5504 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5505 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5506 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5507 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5508 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5509 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5512 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5517 VectorSet(v, x, y, z);
5518 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5519 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5521 if (i == mesh->numvertices)
5523 if (mesh->numvertices < mesh->maxvertices)
5525 VectorCopy(v, vertex3f);
5526 mesh->numvertices++;
5528 return mesh->numvertices;
5534 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5538 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5539 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5540 e = mesh->element3i + mesh->numtriangles * 3;
5541 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5543 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5544 if (mesh->numtriangles < mesh->maxtriangles)
5549 mesh->numtriangles++;
5551 element[1] = element[2];
5555 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5559 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5560 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5561 e = mesh->element3i + mesh->numtriangles * 3;
5562 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5564 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5565 if (mesh->numtriangles < mesh->maxtriangles)
5570 mesh->numtriangles++;
5572 element[1] = element[2];
5576 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5577 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5579 int planenum, planenum2;
5582 mplane_t *plane, *plane2;
5584 double temppoints[2][256*3];
5585 // figure out how large a bounding box we need to properly compute this brush
5587 for (w = 0;w < numplanes;w++)
5588 maxdist = max(maxdist, fabs(planes[w].dist));
5589 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5590 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5591 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5595 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5596 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5598 if (planenum2 == planenum)
5600 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);
5603 if (tempnumpoints < 3)
5605 // generate elements forming a triangle fan for this polygon
5606 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5610 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)
5612 texturelayer_t *layer;
5613 layer = t->currentlayers + t->currentnumlayers++;
5615 layer->depthmask = depthmask;
5616 layer->blendfunc1 = blendfunc1;
5617 layer->blendfunc2 = blendfunc2;
5618 layer->texture = texture;
5619 layer->texmatrix = *matrix;
5620 layer->color[0] = r * r_refdef.view.colorscale;
5621 layer->color[1] = g * r_refdef.view.colorscale;
5622 layer->color[2] = b * r_refdef.view.colorscale;
5623 layer->color[3] = a;
5626 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5629 index = parms[2] + r_refdef.scene.time * parms[3];
5630 index -= floor(index);
5634 case Q3WAVEFUNC_NONE:
5635 case Q3WAVEFUNC_NOISE:
5636 case Q3WAVEFUNC_COUNT:
5639 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5640 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5641 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5642 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5643 case Q3WAVEFUNC_TRIANGLE:
5645 f = index - floor(index);
5656 return (float)(parms[0] + parms[1] * f);
5659 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5664 matrix4x4_t matrix, temp;
5665 switch(tcmod->tcmod)
5669 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5670 matrix = r_waterscrollmatrix;
5672 matrix = identitymatrix;
5674 case Q3TCMOD_ENTITYTRANSLATE:
5675 // this is used in Q3 to allow the gamecode to control texcoord
5676 // scrolling on the entity, which is not supported in darkplaces yet.
5677 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5679 case Q3TCMOD_ROTATE:
5680 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5681 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5682 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5685 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5687 case Q3TCMOD_SCROLL:
5688 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5690 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5691 w = (int) tcmod->parms[0];
5692 h = (int) tcmod->parms[1];
5693 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5695 idx = (int) floor(f * w * h);
5696 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5698 case Q3TCMOD_STRETCH:
5699 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5700 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5702 case Q3TCMOD_TRANSFORM:
5703 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5704 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5705 VectorSet(tcmat + 6, 0 , 0 , 1);
5706 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5707 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5709 case Q3TCMOD_TURBULENT:
5710 // this is handled in the RSurf_PrepareVertices function
5711 matrix = identitymatrix;
5715 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5718 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5720 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5721 char name[MAX_QPATH];
5722 skinframe_t *skinframe;
5723 unsigned char pixels[296*194];
5724 strlcpy(cache->name, skinname, sizeof(cache->name));
5725 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5726 if (developer_loading.integer)
5727 Con_Printf("loading %s\n", name);
5728 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5729 if (!skinframe || !skinframe->base)
5732 fs_offset_t filesize;
5734 f = FS_LoadFile(name, tempmempool, true, &filesize);
5737 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5738 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5742 cache->skinframe = skinframe;
5745 texture_t *R_GetCurrentTexture(texture_t *t)
5748 const entity_render_t *ent = rsurface.entity;
5749 dp_model_t *model = ent->model;
5750 q3shaderinfo_layer_tcmod_t *tcmod;
5752 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5753 return t->currentframe;
5754 t->update_lastrenderframe = r_frame;
5755 t->update_lastrenderentity = (void *)ent;
5757 // switch to an alternate material if this is a q1bsp animated material
5759 texture_t *texture = t;
5760 int s = rsurface.ent_skinnum;
5761 if ((unsigned int)s >= (unsigned int)model->numskins)
5763 if (model->skinscenes)
5765 if (model->skinscenes[s].framecount > 1)
5766 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5768 s = model->skinscenes[s].firstframe;
5771 t = t + s * model->num_surfaces;
5774 // use an alternate animation if the entity's frame is not 0,
5775 // and only if the texture has an alternate animation
5776 if (rsurface.ent_alttextures && t->anim_total[1])
5777 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5779 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5781 texture->currentframe = t;
5784 // update currentskinframe to be a qw skin or animation frame
5785 if (rsurface.ent_qwskin >= 0)
5787 i = rsurface.ent_qwskin;
5788 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5790 r_qwskincache_size = cl.maxclients;
5792 Mem_Free(r_qwskincache);
5793 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5795 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5796 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5797 t->currentskinframe = r_qwskincache[i].skinframe;
5798 if (t->currentskinframe == NULL)
5799 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5801 else if (t->numskinframes >= 2)
5802 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5803 if (t->backgroundnumskinframes >= 2)
5804 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5806 t->currentmaterialflags = t->basematerialflags;
5807 t->currentalpha = rsurface.ent_color[3];
5808 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5809 t->currentalpha *= r_wateralpha.value;
5810 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5811 t->currentalpha *= t->r_water_wateralpha;
5812 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5813 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5814 if (!(rsurface.ent_flags & RENDER_LIGHT))
5815 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5816 else if (rsurface.modeltexcoordlightmap2f == NULL)
5818 // pick a model lighting mode
5819 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5820 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5822 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5824 if (rsurface.ent_flags & RENDER_ADDITIVE)
5825 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5826 else if (t->currentalpha < 1)
5827 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5828 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5829 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5830 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5831 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5832 if (t->backgroundnumskinframes)
5833 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5834 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5836 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5837 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5840 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5842 // there is no tcmod
5843 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5845 t->currenttexmatrix = r_waterscrollmatrix;
5846 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5848 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
5850 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5851 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5854 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5855 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5856 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5857 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5859 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5860 if (t->currentskinframe->qpixels)
5861 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
5862 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5863 t->glosstexture = r_texture_black;
5864 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5865 t->backgroundglosstexture = r_texture_black;
5866 t->specularpower = r_shadow_glossexponent.value;
5867 // TODO: store reference values for these in the texture?
5868 t->specularscale = 0;
5869 if (r_shadow_gloss.integer > 0)
5871 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5873 if (r_shadow_glossintensity.value > 0)
5875 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5876 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5877 t->specularscale = r_shadow_glossintensity.value;
5880 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5882 t->glosstexture = r_texture_white;
5883 t->backgroundglosstexture = r_texture_white;
5884 t->specularscale = r_shadow_gloss2intensity.value;
5885 t->specularpower = r_shadow_gloss2exponent.value;
5888 t->specularscale *= t->specularscalemod;
5889 t->specularpower *= t->specularpowermod;
5891 // lightmaps mode looks bad with dlights using actual texturing, so turn
5892 // off the colormap and glossmap, but leave the normalmap on as it still
5893 // accurately represents the shading involved
5894 if (gl_lightmaps.integer)
5896 t->basetexture = r_texture_grey128;
5897 t->backgroundbasetexture = NULL;
5898 t->specularscale = 0;
5899 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5902 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5903 VectorClear(t->dlightcolor);
5904 t->currentnumlayers = 0;
5905 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5908 int blendfunc1, blendfunc2;
5910 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5912 blendfunc1 = GL_SRC_ALPHA;
5913 blendfunc2 = GL_ONE;
5915 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5917 blendfunc1 = GL_SRC_ALPHA;
5918 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5920 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5922 blendfunc1 = t->customblendfunc[0];
5923 blendfunc2 = t->customblendfunc[1];
5927 blendfunc1 = GL_ONE;
5928 blendfunc2 = GL_ZERO;
5930 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5931 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5932 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5933 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5935 // fullbright is not affected by r_refdef.lightmapintensity
5936 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]);
5937 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5938 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]);
5939 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5940 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]);
5944 vec3_t ambientcolor;
5946 // set the color tint used for lights affecting this surface
5947 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5949 // q3bsp has no lightmap updates, so the lightstylevalue that
5950 // would normally be baked into the lightmap must be
5951 // applied to the color
5952 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5953 if (model->type == mod_brushq3)
5954 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5955 colorscale *= r_refdef.lightmapintensity;
5956 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5957 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5958 // basic lit geometry
5959 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]);
5960 // add pants/shirt if needed
5961 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5962 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]);
5963 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5964 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]);
5965 // now add ambient passes if needed
5966 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5968 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]);
5969 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5970 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]);
5971 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5972 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]);
5975 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5976 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]);
5977 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5979 // if this is opaque use alpha blend which will darken the earlier
5982 // if this is an alpha blended material, all the earlier passes
5983 // were darkened by fog already, so we only need to add the fog
5984 // color ontop through the fog mask texture
5986 // if this is an additive blended material, all the earlier passes
5987 // were darkened by fog already, and we should not add fog color
5988 // (because the background was not darkened, there is no fog color
5989 // that was lost behind it).
5990 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]);
5994 return t->currentframe;
5997 rsurfacestate_t rsurface;
5999 void R_Mesh_ResizeArrays(int newvertices)
6002 if (rsurface.array_size >= newvertices)
6004 if (rsurface.array_modelvertex3f)
6005 Mem_Free(rsurface.array_modelvertex3f);
6006 rsurface.array_size = (newvertices + 1023) & ~1023;
6007 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
6008 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
6009 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
6010 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
6011 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
6012 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
6013 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
6014 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
6015 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
6016 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
6017 rsurface.array_color4f = base + rsurface.array_size * 27;
6018 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6021 void RSurf_ActiveWorldEntity(void)
6023 dp_model_t *model = r_refdef.scene.worldmodel;
6024 //if (rsurface.entity == r_refdef.scene.worldentity)
6026 rsurface.entity = r_refdef.scene.worldentity;
6027 rsurface.skeleton = NULL;
6028 rsurface.ent_skinnum = 0;
6029 rsurface.ent_qwskin = -1;
6030 rsurface.ent_shadertime = 0;
6031 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
6032 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6033 if (rsurface.array_size < model->surfmesh.num_vertices)
6034 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6035 rsurface.matrix = identitymatrix;
6036 rsurface.inversematrix = identitymatrix;
6037 rsurface.matrixscale = 1;
6038 rsurface.inversematrixscale = 1;
6039 R_Mesh_Matrix(&identitymatrix);
6040 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6041 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6042 rsurface.fograngerecip = r_refdef.fograngerecip;
6043 rsurface.fogheightfade = r_refdef.fogheightfade;
6044 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6045 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6046 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6047 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6048 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6049 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6050 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6051 VectorSet(rsurface.glowmod, 1, 1, 1);
6052 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6053 rsurface.frameblend[0].lerp = 1;
6054 rsurface.ent_alttextures = false;
6055 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6056 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6057 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6058 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6059 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6060 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6061 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6062 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6063 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6064 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6065 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6066 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6067 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6068 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6069 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6070 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6071 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6072 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6073 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6074 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6075 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6076 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6077 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6078 rsurface.modelelement3i = model->surfmesh.data_element3i;
6079 rsurface.modelelement3s = model->surfmesh.data_element3s;
6080 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6081 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6082 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6083 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6084 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6085 rsurface.modelsurfaces = model->data_surfaces;
6086 rsurface.generatedvertex = false;
6087 rsurface.vertex3f = rsurface.modelvertex3f;
6088 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6089 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6090 rsurface.svector3f = rsurface.modelsvector3f;
6091 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6092 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6093 rsurface.tvector3f = rsurface.modeltvector3f;
6094 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6095 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6096 rsurface.normal3f = rsurface.modelnormal3f;
6097 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6098 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6099 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6102 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6104 dp_model_t *model = ent->model;
6105 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6107 rsurface.entity = (entity_render_t *)ent;
6108 rsurface.skeleton = ent->skeleton;
6109 rsurface.ent_skinnum = ent->skinnum;
6110 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;
6111 rsurface.ent_shadertime = ent->shadertime;
6112 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6113 rsurface.ent_flags = ent->flags;
6114 if (rsurface.array_size < model->surfmesh.num_vertices)
6115 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6116 rsurface.matrix = ent->matrix;
6117 rsurface.inversematrix = ent->inversematrix;
6118 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6119 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6120 R_Mesh_Matrix(&rsurface.matrix);
6121 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6122 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6123 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6124 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6125 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6126 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6127 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6128 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6129 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6130 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6131 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6132 VectorCopy(ent->glowmod, rsurface.glowmod);
6133 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6134 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6135 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6136 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6137 if (ent->model->brush.submodel)
6139 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6140 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6142 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6144 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6146 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6147 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6148 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6149 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6151 else if (wanttangents)
6153 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6154 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6155 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6156 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6157 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6159 else if (wantnormals)
6161 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6162 rsurface.modelsvector3f = NULL;
6163 rsurface.modeltvector3f = NULL;
6164 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6165 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6169 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6170 rsurface.modelsvector3f = NULL;
6171 rsurface.modeltvector3f = NULL;
6172 rsurface.modelnormal3f = NULL;
6173 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6175 rsurface.modelvertex3f_bufferobject = 0;
6176 rsurface.modelvertex3f_bufferoffset = 0;
6177 rsurface.modelsvector3f_bufferobject = 0;
6178 rsurface.modelsvector3f_bufferoffset = 0;
6179 rsurface.modeltvector3f_bufferobject = 0;
6180 rsurface.modeltvector3f_bufferoffset = 0;
6181 rsurface.modelnormal3f_bufferobject = 0;
6182 rsurface.modelnormal3f_bufferoffset = 0;
6183 rsurface.generatedvertex = true;
6187 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6188 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6189 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6190 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6191 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6192 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6193 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6194 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6195 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6196 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6197 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6198 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6199 rsurface.generatedvertex = false;
6201 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6202 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6203 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6204 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6205 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6206 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6207 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6208 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6209 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6210 rsurface.modelelement3i = model->surfmesh.data_element3i;
6211 rsurface.modelelement3s = model->surfmesh.data_element3s;
6212 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6213 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6214 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6215 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6216 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6217 rsurface.modelsurfaces = model->data_surfaces;
6218 rsurface.vertex3f = rsurface.modelvertex3f;
6219 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6220 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6221 rsurface.svector3f = rsurface.modelsvector3f;
6222 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6223 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6224 rsurface.tvector3f = rsurface.modeltvector3f;
6225 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6226 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6227 rsurface.normal3f = rsurface.modelnormal3f;
6228 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6229 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6230 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6233 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)
6235 rsurface.entity = r_refdef.scene.worldentity;
6236 rsurface.skeleton = NULL;
6237 rsurface.ent_skinnum = 0;
6238 rsurface.ent_qwskin = -1;
6239 rsurface.ent_shadertime = shadertime;
6240 Vector4Set(rsurface.ent_color, r, g, b, a);
6241 rsurface.ent_flags = entflags;
6242 rsurface.modelnum_vertices = numvertices;
6243 rsurface.modelnum_triangles = numtriangles;
6244 if (rsurface.array_size < rsurface.modelnum_vertices)
6245 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6246 rsurface.matrix = *matrix;
6247 rsurface.inversematrix = *inversematrix;
6248 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6249 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6250 R_Mesh_Matrix(&rsurface.matrix);
6251 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6252 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6253 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6254 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6255 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6256 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6257 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6258 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6259 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6260 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6261 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6262 VectorSet(rsurface.glowmod, 1, 1, 1);
6263 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6264 rsurface.frameblend[0].lerp = 1;
6265 rsurface.ent_alttextures = false;
6266 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6267 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6270 rsurface.modelvertex3f = vertex3f;
6271 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6272 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6273 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6275 else if (wantnormals)
6277 rsurface.modelvertex3f = vertex3f;
6278 rsurface.modelsvector3f = NULL;
6279 rsurface.modeltvector3f = NULL;
6280 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6284 rsurface.modelvertex3f = vertex3f;
6285 rsurface.modelsvector3f = NULL;
6286 rsurface.modeltvector3f = NULL;
6287 rsurface.modelnormal3f = NULL;
6289 rsurface.modelvertex3f_bufferobject = 0;
6290 rsurface.modelvertex3f_bufferoffset = 0;
6291 rsurface.modelsvector3f_bufferobject = 0;
6292 rsurface.modelsvector3f_bufferoffset = 0;
6293 rsurface.modeltvector3f_bufferobject = 0;
6294 rsurface.modeltvector3f_bufferoffset = 0;
6295 rsurface.modelnormal3f_bufferobject = 0;
6296 rsurface.modelnormal3f_bufferoffset = 0;
6297 rsurface.generatedvertex = true;
6298 rsurface.modellightmapcolor4f = color4f;
6299 rsurface.modellightmapcolor4f_bufferobject = 0;
6300 rsurface.modellightmapcolor4f_bufferoffset = 0;
6301 rsurface.modeltexcoordtexture2f = texcoord2f;
6302 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6303 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6304 rsurface.modeltexcoordlightmap2f = NULL;
6305 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6306 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6307 rsurface.modelelement3i = element3i;
6308 rsurface.modelelement3s = element3s;
6309 rsurface.modelelement3i_bufferobject = 0;
6310 rsurface.modelelement3s_bufferobject = 0;
6311 rsurface.modellightmapoffsets = NULL;
6312 rsurface.modelsurfaces = NULL;
6313 rsurface.vertex3f = rsurface.modelvertex3f;
6314 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6315 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6316 rsurface.svector3f = rsurface.modelsvector3f;
6317 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6318 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6319 rsurface.tvector3f = rsurface.modeltvector3f;
6320 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6321 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6322 rsurface.normal3f = rsurface.modelnormal3f;
6323 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6324 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6325 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6327 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6329 if ((wantnormals || wanttangents) && !normal3f)
6330 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6331 if (wanttangents && !svector3f)
6332 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);
6336 float RSurf_FogPoint(const float *v)
6338 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6339 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6340 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6341 float FogHeightFade = r_refdef.fogheightfade;
6343 unsigned int fogmasktableindex;
6344 if (r_refdef.fogplaneviewabove)
6345 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6347 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6348 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6349 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6352 float RSurf_FogVertex(const float *v)
6354 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6355 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6356 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6357 float FogHeightFade = rsurface.fogheightfade;
6359 unsigned int fogmasktableindex;
6360 if (r_refdef.fogplaneviewabove)
6361 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6363 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6364 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6365 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6368 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6369 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6372 int texturesurfaceindex;
6377 const float *v1, *in_tc;
6379 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6381 q3shaderinfo_deform_t *deform;
6382 // 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
6383 if (rsurface.generatedvertex)
6385 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6386 generatenormals = true;
6387 for (i = 0;i < Q3MAXDEFORMS;i++)
6389 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6391 generatetangents = true;
6392 generatenormals = true;
6394 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6395 generatenormals = true;
6397 if (generatenormals && !rsurface.modelnormal3f)
6399 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6400 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6401 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6402 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6404 if (generatetangents && !rsurface.modelsvector3f)
6406 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6407 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6408 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6409 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6410 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6411 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6412 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);
6415 rsurface.vertex3f = rsurface.modelvertex3f;
6416 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6417 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6418 rsurface.svector3f = rsurface.modelsvector3f;
6419 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6420 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6421 rsurface.tvector3f = rsurface.modeltvector3f;
6422 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6423 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6424 rsurface.normal3f = rsurface.modelnormal3f;
6425 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6426 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6427 // if vertices are deformed (sprite flares and things in maps, possibly
6428 // water waves, bulges and other deformations), generate them into
6429 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6430 // (may be static model data or generated data for an animated model, or
6431 // the previous deform pass)
6432 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6434 switch (deform->deform)
6437 case Q3DEFORM_PROJECTIONSHADOW:
6438 case Q3DEFORM_TEXT0:
6439 case Q3DEFORM_TEXT1:
6440 case Q3DEFORM_TEXT2:
6441 case Q3DEFORM_TEXT3:
6442 case Q3DEFORM_TEXT4:
6443 case Q3DEFORM_TEXT5:
6444 case Q3DEFORM_TEXT6:
6445 case Q3DEFORM_TEXT7:
6448 case Q3DEFORM_AUTOSPRITE:
6449 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6450 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6451 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6452 VectorNormalize(newforward);
6453 VectorNormalize(newright);
6454 VectorNormalize(newup);
6455 // make deformed versions of only the model vertices used by the specified surfaces
6456 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6458 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6459 // a single autosprite surface can contain multiple sprites...
6460 for (j = 0;j < surface->num_vertices - 3;j += 4)
6462 VectorClear(center);
6463 for (i = 0;i < 4;i++)
6464 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6465 VectorScale(center, 0.25f, center);
6466 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6467 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6468 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6469 for (i = 0;i < 4;i++)
6471 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6472 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6475 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);
6476 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);
6478 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6479 rsurface.vertex3f_bufferobject = 0;
6480 rsurface.vertex3f_bufferoffset = 0;
6481 rsurface.svector3f = rsurface.array_deformedsvector3f;
6482 rsurface.svector3f_bufferobject = 0;
6483 rsurface.svector3f_bufferoffset = 0;
6484 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6485 rsurface.tvector3f_bufferobject = 0;
6486 rsurface.tvector3f_bufferoffset = 0;
6487 rsurface.normal3f = rsurface.array_deformednormal3f;
6488 rsurface.normal3f_bufferobject = 0;
6489 rsurface.normal3f_bufferoffset = 0;
6491 case Q3DEFORM_AUTOSPRITE2:
6492 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6493 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6494 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6495 VectorNormalize(newforward);
6496 VectorNormalize(newright);
6497 VectorNormalize(newup);
6498 // make deformed versions of only the model vertices used by the specified surfaces
6499 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6501 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6502 const float *v1, *v2;
6512 memset(shortest, 0, sizeof(shortest));
6513 // a single autosprite surface can contain multiple sprites...
6514 for (j = 0;j < surface->num_vertices - 3;j += 4)
6516 VectorClear(center);
6517 for (i = 0;i < 4;i++)
6518 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6519 VectorScale(center, 0.25f, center);
6520 // find the two shortest edges, then use them to define the
6521 // axis vectors for rotating around the central axis
6522 for (i = 0;i < 6;i++)
6524 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6525 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6527 Debug_PolygonBegin(NULL, 0);
6528 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6529 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);
6530 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6533 l = VectorDistance2(v1, v2);
6534 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6536 l += (1.0f / 1024.0f);
6537 if (shortest[0].length2 > l || i == 0)
6539 shortest[1] = shortest[0];
6540 shortest[0].length2 = l;
6541 shortest[0].v1 = v1;
6542 shortest[0].v2 = v2;
6544 else if (shortest[1].length2 > l || i == 1)
6546 shortest[1].length2 = l;
6547 shortest[1].v1 = v1;
6548 shortest[1].v2 = v2;
6551 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6552 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6554 Debug_PolygonBegin(NULL, 0);
6555 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6556 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);
6557 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6560 // this calculates the right vector from the shortest edge
6561 // and the up vector from the edge midpoints
6562 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6563 VectorNormalize(right);
6564 VectorSubtract(end, start, up);
6565 VectorNormalize(up);
6566 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6567 VectorSubtract(rsurface.localvieworigin, center, forward);
6568 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6569 VectorNegate(forward, forward);
6570 VectorReflect(forward, 0, up, forward);
6571 VectorNormalize(forward);
6572 CrossProduct(up, forward, newright);
6573 VectorNormalize(newright);
6575 Debug_PolygonBegin(NULL, 0);
6576 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);
6577 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6578 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6582 Debug_PolygonBegin(NULL, 0);
6583 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6584 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6585 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6588 // rotate the quad around the up axis vector, this is made
6589 // especially easy by the fact we know the quad is flat,
6590 // so we only have to subtract the center position and
6591 // measure distance along the right vector, and then
6592 // multiply that by the newright vector and add back the
6594 // we also need to subtract the old position to undo the
6595 // displacement from the center, which we do with a
6596 // DotProduct, the subtraction/addition of center is also
6597 // optimized into DotProducts here
6598 l = DotProduct(right, center);
6599 for (i = 0;i < 4;i++)
6601 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6602 f = DotProduct(right, v1) - l;
6603 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6606 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);
6607 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);
6609 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6610 rsurface.vertex3f_bufferobject = 0;
6611 rsurface.vertex3f_bufferoffset = 0;
6612 rsurface.svector3f = rsurface.array_deformedsvector3f;
6613 rsurface.svector3f_bufferobject = 0;
6614 rsurface.svector3f_bufferoffset = 0;
6615 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6616 rsurface.tvector3f_bufferobject = 0;
6617 rsurface.tvector3f_bufferoffset = 0;
6618 rsurface.normal3f = rsurface.array_deformednormal3f;
6619 rsurface.normal3f_bufferobject = 0;
6620 rsurface.normal3f_bufferoffset = 0;
6622 case Q3DEFORM_NORMAL:
6623 // deform the normals to make reflections wavey
6624 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6626 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6627 for (j = 0;j < surface->num_vertices;j++)
6630 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6631 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6632 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6633 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6634 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6635 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6636 VectorNormalize(normal);
6638 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);
6640 rsurface.svector3f = rsurface.array_deformedsvector3f;
6641 rsurface.svector3f_bufferobject = 0;
6642 rsurface.svector3f_bufferoffset = 0;
6643 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6644 rsurface.tvector3f_bufferobject = 0;
6645 rsurface.tvector3f_bufferoffset = 0;
6646 rsurface.normal3f = rsurface.array_deformednormal3f;
6647 rsurface.normal3f_bufferobject = 0;
6648 rsurface.normal3f_bufferoffset = 0;
6651 // deform vertex array to make wavey water and flags and such
6652 waveparms[0] = deform->waveparms[0];
6653 waveparms[1] = deform->waveparms[1];
6654 waveparms[2] = deform->waveparms[2];
6655 waveparms[3] = deform->waveparms[3];
6656 // this is how a divisor of vertex influence on deformation
6657 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6658 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6659 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6661 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6662 for (j = 0;j < surface->num_vertices;j++)
6664 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6665 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6666 // if the wavefunc depends on time, evaluate it per-vertex
6669 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6670 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6672 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6675 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6676 rsurface.vertex3f_bufferobject = 0;
6677 rsurface.vertex3f_bufferoffset = 0;
6679 case Q3DEFORM_BULGE:
6680 // deform vertex array to make the surface have moving bulges
6681 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6683 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6684 for (j = 0;j < surface->num_vertices;j++)
6686 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6687 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6690 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6691 rsurface.vertex3f_bufferobject = 0;
6692 rsurface.vertex3f_bufferoffset = 0;
6695 // deform vertex array
6696 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6697 VectorScale(deform->parms, scale, waveparms);
6698 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6700 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6701 for (j = 0;j < surface->num_vertices;j++)
6702 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6704 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6705 rsurface.vertex3f_bufferobject = 0;
6706 rsurface.vertex3f_bufferoffset = 0;
6710 // generate texcoords based on the chosen texcoord source
6711 switch(rsurface.texture->tcgen.tcgen)
6714 case Q3TCGEN_TEXTURE:
6715 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6716 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6717 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6719 case Q3TCGEN_LIGHTMAP:
6720 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6721 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6722 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6724 case Q3TCGEN_VECTOR:
6725 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6727 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6728 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)
6730 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6731 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6734 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6735 rsurface.texcoordtexture2f_bufferobject = 0;
6736 rsurface.texcoordtexture2f_bufferoffset = 0;
6738 case Q3TCGEN_ENVIRONMENT:
6739 // make environment reflections using a spheremap
6740 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6742 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6743 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6744 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6745 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6746 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6748 // identical to Q3A's method, but executed in worldspace so
6749 // carried models can be shiny too
6751 float viewer[3], d, reflected[3], worldreflected[3];
6753 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6754 // VectorNormalize(viewer);
6756 d = DotProduct(normal, viewer);
6758 reflected[0] = normal[0]*2*d - viewer[0];
6759 reflected[1] = normal[1]*2*d - viewer[1];
6760 reflected[2] = normal[2]*2*d - viewer[2];
6761 // note: this is proportinal to viewer, so we can normalize later
6763 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6764 VectorNormalize(worldreflected);
6766 // note: this sphere map only uses world x and z!
6767 // so positive and negative y will LOOK THE SAME.
6768 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6769 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6772 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6773 rsurface.texcoordtexture2f_bufferobject = 0;
6774 rsurface.texcoordtexture2f_bufferoffset = 0;
6777 // the only tcmod that needs software vertex processing is turbulent, so
6778 // check for it here and apply the changes if needed
6779 // and we only support that as the first one
6780 // (handling a mixture of turbulent and other tcmods would be problematic
6781 // without punting it entirely to a software path)
6782 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6784 amplitude = rsurface.texture->tcmods[0].parms[1];
6785 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6786 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6788 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6789 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)
6791 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6792 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6795 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6796 rsurface.texcoordtexture2f_bufferobject = 0;
6797 rsurface.texcoordtexture2f_bufferoffset = 0;
6799 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6800 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6801 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6802 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6805 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6808 const msurface_t *surface = texturesurfacelist[0];
6809 const msurface_t *surface2;
6814 // TODO: lock all array ranges before render, rather than on each surface
6815 if (texturenumsurfaces == 1)
6817 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6818 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);
6820 else if (r_batchmode.integer == 2)
6822 #define MAXBATCHTRIANGLES 4096
6823 int batchtriangles = 0;
6824 int batchelements[MAXBATCHTRIANGLES*3];
6825 for (i = 0;i < texturenumsurfaces;i = j)
6827 surface = texturesurfacelist[i];
6829 if (surface->num_triangles > MAXBATCHTRIANGLES)
6831 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);
6834 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6835 batchtriangles = surface->num_triangles;
6836 firstvertex = surface->num_firstvertex;
6837 endvertex = surface->num_firstvertex + surface->num_vertices;
6838 for (;j < texturenumsurfaces;j++)
6840 surface2 = texturesurfacelist[j];
6841 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6843 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6844 batchtriangles += surface2->num_triangles;
6845 firstvertex = min(firstvertex, surface2->num_firstvertex);
6846 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6848 surface2 = texturesurfacelist[j-1];
6849 numvertices = endvertex - firstvertex;
6850 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6853 else if (r_batchmode.integer == 1)
6855 for (i = 0;i < texturenumsurfaces;i = j)
6857 surface = texturesurfacelist[i];
6858 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6859 if (texturesurfacelist[j] != surface2)
6861 surface2 = texturesurfacelist[j-1];
6862 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6863 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6864 GL_LockArrays(surface->num_firstvertex, numvertices);
6865 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6870 for (i = 0;i < texturenumsurfaces;i++)
6872 surface = texturesurfacelist[i];
6873 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6874 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);
6879 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6881 int i, planeindex, vertexindex;
6885 r_waterstate_waterplane_t *p, *bestp;
6886 const msurface_t *surface;
6887 if (r_waterstate.renderingscene)
6889 for (i = 0;i < texturenumsurfaces;i++)
6891 surface = texturesurfacelist[i];
6892 if (lightmaptexunit >= 0)
6893 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6894 if (deluxemaptexunit >= 0)
6895 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6896 // pick the closest matching water plane
6899 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6902 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6904 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6905 d += fabs(PlaneDiff(vert, &p->plane));
6907 if (bestd > d || !bestp)
6915 if (refractiontexunit >= 0)
6916 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6917 if (reflectiontexunit >= 0)
6918 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6922 if (refractiontexunit >= 0)
6923 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6924 if (reflectiontexunit >= 0)
6925 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6927 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6928 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);
6932 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6936 const msurface_t *surface = texturesurfacelist[0];
6937 const msurface_t *surface2;
6942 // TODO: lock all array ranges before render, rather than on each surface
6943 if (texturenumsurfaces == 1)
6945 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6946 if (deluxemaptexunit >= 0)
6947 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6948 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6949 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);
6951 else if (r_batchmode.integer == 2)
6953 #define MAXBATCHTRIANGLES 4096
6954 int batchtriangles = 0;
6955 int batchelements[MAXBATCHTRIANGLES*3];
6956 for (i = 0;i < texturenumsurfaces;i = j)
6958 surface = texturesurfacelist[i];
6959 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6960 if (deluxemaptexunit >= 0)
6961 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6963 if (surface->num_triangles > MAXBATCHTRIANGLES)
6965 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);
6968 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6969 batchtriangles = surface->num_triangles;
6970 firstvertex = surface->num_firstvertex;
6971 endvertex = surface->num_firstvertex + surface->num_vertices;
6972 for (;j < texturenumsurfaces;j++)
6974 surface2 = texturesurfacelist[j];
6975 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6977 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6978 batchtriangles += surface2->num_triangles;
6979 firstvertex = min(firstvertex, surface2->num_firstvertex);
6980 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6982 surface2 = texturesurfacelist[j-1];
6983 numvertices = endvertex - firstvertex;
6984 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6987 else if (r_batchmode.integer == 1)
6990 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6991 for (i = 0;i < texturenumsurfaces;i = j)
6993 surface = texturesurfacelist[i];
6994 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6995 if (texturesurfacelist[j] != surface2)
6997 Con_Printf(" %i", j - i);
7000 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
7002 for (i = 0;i < texturenumsurfaces;i = j)
7004 surface = texturesurfacelist[i];
7005 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7006 if (deluxemaptexunit >= 0)
7007 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7008 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7009 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
7012 Con_Printf(" %i", j - i);
7014 surface2 = texturesurfacelist[j-1];
7015 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7016 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7017 GL_LockArrays(surface->num_firstvertex, numvertices);
7018 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7026 for (i = 0;i < texturenumsurfaces;i++)
7028 surface = texturesurfacelist[i];
7029 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7030 if (deluxemaptexunit >= 0)
7031 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7032 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7033 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);
7038 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7041 int texturesurfaceindex;
7042 if (r_showsurfaces.integer == 2)
7044 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7046 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7047 for (j = 0;j < surface->num_triangles;j++)
7049 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7050 GL_Color(f, f, f, 1);
7051 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7057 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7059 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7060 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7061 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);
7062 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7063 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);
7068 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7070 int texturesurfaceindex;
7074 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7076 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7077 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)
7085 rsurface.lightmapcolor4f = rsurface.array_color4f;
7086 rsurface.lightmapcolor4f_bufferobject = 0;
7087 rsurface.lightmapcolor4f_bufferoffset = 0;
7090 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7092 int texturesurfaceindex;
7098 if (rsurface.lightmapcolor4f)
7100 // generate color arrays for the surfaces in this list
7101 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7103 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7104 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)
7106 f = RSurf_FogVertex(v);
7116 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7118 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7119 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)
7121 f = RSurf_FogVertex(v);
7129 rsurface.lightmapcolor4f = rsurface.array_color4f;
7130 rsurface.lightmapcolor4f_bufferobject = 0;
7131 rsurface.lightmapcolor4f_bufferoffset = 0;
7134 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7136 int texturesurfaceindex;
7142 if (!rsurface.lightmapcolor4f)
7144 // generate color arrays for the surfaces in this list
7145 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7147 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7148 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)
7150 f = RSurf_FogVertex(v);
7151 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7152 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7153 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7157 rsurface.lightmapcolor4f = rsurface.array_color4f;
7158 rsurface.lightmapcolor4f_bufferobject = 0;
7159 rsurface.lightmapcolor4f_bufferoffset = 0;
7162 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7164 int texturesurfaceindex;
7168 if (!rsurface.lightmapcolor4f)
7170 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7172 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7173 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)
7181 rsurface.lightmapcolor4f = rsurface.array_color4f;
7182 rsurface.lightmapcolor4f_bufferobject = 0;
7183 rsurface.lightmapcolor4f_bufferoffset = 0;
7186 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7188 int texturesurfaceindex;
7192 if (!rsurface.lightmapcolor4f)
7194 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7196 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7197 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)
7199 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7200 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7201 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7205 rsurface.lightmapcolor4f = rsurface.array_color4f;
7206 rsurface.lightmapcolor4f_bufferobject = 0;
7207 rsurface.lightmapcolor4f_bufferoffset = 0;
7210 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7213 rsurface.lightmapcolor4f = NULL;
7214 rsurface.lightmapcolor4f_bufferobject = 0;
7215 rsurface.lightmapcolor4f_bufferoffset = 0;
7216 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7217 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7218 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7219 GL_Color(r, g, b, a);
7220 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7223 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7225 // TODO: optimize applyfog && applycolor case
7226 // just apply fog if necessary, and tint the fog color array if necessary
7227 rsurface.lightmapcolor4f = NULL;
7228 rsurface.lightmapcolor4f_bufferobject = 0;
7229 rsurface.lightmapcolor4f_bufferoffset = 0;
7230 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7231 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7232 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7233 GL_Color(r, g, b, a);
7234 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7237 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7239 int texturesurfaceindex;
7243 if (texturesurfacelist[0]->lightmapinfo)
7245 // generate color arrays for the surfaces in this list
7246 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7248 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7249 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7251 if (surface->lightmapinfo->samples)
7253 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7254 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7255 VectorScale(lm, scale, c);
7256 if (surface->lightmapinfo->styles[1] != 255)
7258 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7260 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7261 VectorMA(c, scale, lm, c);
7262 if (surface->lightmapinfo->styles[2] != 255)
7265 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7266 VectorMA(c, scale, lm, c);
7267 if (surface->lightmapinfo->styles[3] != 255)
7270 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7271 VectorMA(c, scale, lm, c);
7281 rsurface.lightmapcolor4f = rsurface.array_color4f;
7282 rsurface.lightmapcolor4f_bufferobject = 0;
7283 rsurface.lightmapcolor4f_bufferoffset = 0;
7287 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7288 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7289 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7291 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7292 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7293 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7294 GL_Color(r, g, b, a);
7295 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7298 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7300 int texturesurfaceindex;
7307 vec3_t ambientcolor;
7308 vec3_t diffusecolor;
7312 VectorCopy(rsurface.modellight_lightdir, lightdir);
7313 f = 0.5f * r_refdef.lightmapintensity;
7314 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7315 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7316 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7317 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7318 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7319 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7321 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7323 // generate color arrays for the surfaces in this list
7324 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7326 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7327 int numverts = surface->num_vertices;
7328 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7329 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7330 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7331 // q3-style directional shading
7332 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7334 if ((f = DotProduct(n, lightdir)) > 0)
7335 VectorMA(ambientcolor, f, diffusecolor, c);
7337 VectorCopy(ambientcolor, c);
7345 rsurface.lightmapcolor4f = rsurface.array_color4f;
7346 rsurface.lightmapcolor4f_bufferobject = 0;
7347 rsurface.lightmapcolor4f_bufferoffset = 0;
7348 *applycolor = false;
7352 *r = ambientcolor[0];
7353 *g = ambientcolor[1];
7354 *b = ambientcolor[2];
7355 rsurface.lightmapcolor4f = NULL;
7356 rsurface.lightmapcolor4f_bufferobject = 0;
7357 rsurface.lightmapcolor4f_bufferoffset = 0;
7361 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7363 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7364 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7365 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7366 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7367 GL_Color(r, g, b, a);
7368 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7371 void RSurf_SetupDepthAndCulling(void)
7373 // submodels are biased to avoid z-fighting with world surfaces that they
7374 // may be exactly overlapping (avoids z-fighting artifacts on certain
7375 // doors and things in Quake maps)
7376 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7377 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7378 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7379 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7382 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7384 // transparent sky would be ridiculous
7385 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7387 R_SetupGenericShader(false);
7388 skyrenderlater = true;
7389 RSurf_SetupDepthAndCulling();
7391 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7392 // skymasking on them, and Quake3 never did sky masking (unlike
7393 // software Quake and software Quake2), so disable the sky masking
7394 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7395 // and skymasking also looks very bad when noclipping outside the
7396 // level, so don't use it then either.
7397 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7399 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7400 R_Mesh_ColorPointer(NULL, 0, 0);
7401 R_Mesh_ResetTextureState();
7402 if (skyrendermasked)
7404 R_SetupDepthOrShadowShader();
7405 // depth-only (masking)
7406 GL_ColorMask(0,0,0,0);
7407 // just to make sure that braindead drivers don't draw
7408 // anything despite that colormask...
7409 GL_BlendFunc(GL_ZERO, GL_ONE);
7413 R_SetupGenericShader(false);
7415 GL_BlendFunc(GL_ONE, GL_ZERO);
7417 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7418 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7419 if (skyrendermasked)
7420 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7422 R_Mesh_ResetTextureState();
7423 GL_Color(1, 1, 1, 1);
7426 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7428 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7431 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7432 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7433 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7434 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7435 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7436 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7437 if (rsurface.texture->backgroundcurrentskinframe)
7439 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7440 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7441 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7442 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7444 if(rsurface.texture->colormapping)
7446 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7447 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7449 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7450 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7451 R_Mesh_ColorPointer(NULL, 0, 0);
7453 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7455 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7457 // render background
7458 GL_BlendFunc(GL_ONE, GL_ZERO);
7460 GL_AlphaTest(false);
7462 GL_Color(1, 1, 1, 1);
7463 R_Mesh_ColorPointer(NULL, 0, 0);
7465 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7466 if (r_glsl_permutation)
7468 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7469 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7470 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7471 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7472 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7473 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7474 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);
7476 GL_LockArrays(0, 0);
7478 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7479 GL_DepthMask(false);
7480 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7481 R_Mesh_ColorPointer(NULL, 0, 0);
7483 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7484 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7485 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7488 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7489 if (!r_glsl_permutation)
7492 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7493 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7494 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7495 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7496 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7497 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7499 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7501 GL_BlendFunc(GL_ONE, GL_ZERO);
7503 GL_AlphaTest(false);
7507 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7508 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7509 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7512 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7514 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7515 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);
7517 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7521 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7522 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);
7524 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7526 GL_LockArrays(0, 0);
7529 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7531 // OpenGL 1.3 path - anything not completely ancient
7532 int texturesurfaceindex;
7533 qboolean applycolor;
7537 const texturelayer_t *layer;
7538 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7540 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7543 int layertexrgbscale;
7544 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7546 if (layerindex == 0)
7550 GL_AlphaTest(false);
7551 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7554 GL_DepthMask(layer->depthmask && writedepth);
7555 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7556 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7558 layertexrgbscale = 4;
7559 VectorScale(layer->color, 0.25f, layercolor);
7561 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7563 layertexrgbscale = 2;
7564 VectorScale(layer->color, 0.5f, layercolor);
7568 layertexrgbscale = 1;
7569 VectorScale(layer->color, 1.0f, layercolor);
7571 layercolor[3] = layer->color[3];
7572 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7573 R_Mesh_ColorPointer(NULL, 0, 0);
7574 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7575 switch (layer->type)
7577 case TEXTURELAYERTYPE_LITTEXTURE:
7578 memset(&m, 0, sizeof(m));
7579 m.tex[0] = R_GetTexture(r_texture_white);
7580 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7581 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7582 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7583 m.tex[1] = R_GetTexture(layer->texture);
7584 m.texmatrix[1] = layer->texmatrix;
7585 m.texrgbscale[1] = layertexrgbscale;
7586 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7587 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7588 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7589 R_Mesh_TextureState(&m);
7590 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7591 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7592 else if (rsurface.uselightmaptexture)
7593 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7595 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7597 case TEXTURELAYERTYPE_TEXTURE:
7598 memset(&m, 0, sizeof(m));
7599 m.tex[0] = R_GetTexture(layer->texture);
7600 m.texmatrix[0] = layer->texmatrix;
7601 m.texrgbscale[0] = layertexrgbscale;
7602 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7603 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7604 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7605 R_Mesh_TextureState(&m);
7606 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7608 case TEXTURELAYERTYPE_FOG:
7609 memset(&m, 0, sizeof(m));
7610 m.texrgbscale[0] = layertexrgbscale;
7613 m.tex[0] = R_GetTexture(layer->texture);
7614 m.texmatrix[0] = layer->texmatrix;
7615 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7616 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7617 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7619 R_Mesh_TextureState(&m);
7620 // generate a color array for the fog pass
7621 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7622 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7628 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7629 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)
7631 f = 1 - RSurf_FogVertex(v);
7632 c[0] = layercolor[0];
7633 c[1] = layercolor[1];
7634 c[2] = layercolor[2];
7635 c[3] = f * layercolor[3];
7638 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7641 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7643 GL_LockArrays(0, 0);
7646 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7648 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7649 GL_AlphaTest(false);
7653 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7655 // OpenGL 1.1 - crusty old voodoo path
7656 int texturesurfaceindex;
7660 const texturelayer_t *layer;
7661 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7663 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7665 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7667 if (layerindex == 0)
7671 GL_AlphaTest(false);
7672 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7675 GL_DepthMask(layer->depthmask && writedepth);
7676 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7677 R_Mesh_ColorPointer(NULL, 0, 0);
7678 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7679 switch (layer->type)
7681 case TEXTURELAYERTYPE_LITTEXTURE:
7682 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7684 // two-pass lit texture with 2x rgbscale
7685 // first the lightmap pass
7686 memset(&m, 0, sizeof(m));
7687 m.tex[0] = R_GetTexture(r_texture_white);
7688 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7689 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7690 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7691 R_Mesh_TextureState(&m);
7692 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7693 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7694 else if (rsurface.uselightmaptexture)
7695 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7697 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7698 GL_LockArrays(0, 0);
7699 // then apply the texture to it
7700 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7701 memset(&m, 0, sizeof(m));
7702 m.tex[0] = R_GetTexture(layer->texture);
7703 m.texmatrix[0] = layer->texmatrix;
7704 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7705 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7706 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7707 R_Mesh_TextureState(&m);
7708 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);
7712 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7713 memset(&m, 0, sizeof(m));
7714 m.tex[0] = R_GetTexture(layer->texture);
7715 m.texmatrix[0] = layer->texmatrix;
7716 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7717 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7718 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7719 R_Mesh_TextureState(&m);
7720 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7721 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);
7723 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);
7726 case TEXTURELAYERTYPE_TEXTURE:
7727 // singletexture unlit texture with transparency support
7728 memset(&m, 0, sizeof(m));
7729 m.tex[0] = R_GetTexture(layer->texture);
7730 m.texmatrix[0] = layer->texmatrix;
7731 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7732 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7733 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7734 R_Mesh_TextureState(&m);
7735 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);
7737 case TEXTURELAYERTYPE_FOG:
7738 // singletexture fogging
7739 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7742 memset(&m, 0, sizeof(m));
7743 m.tex[0] = R_GetTexture(layer->texture);
7744 m.texmatrix[0] = layer->texmatrix;
7745 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7746 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7747 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7748 R_Mesh_TextureState(&m);
7751 R_Mesh_ResetTextureState();
7752 // generate a color array for the fog pass
7753 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7759 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7760 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)
7762 f = 1 - RSurf_FogVertex(v);
7763 c[0] = layer->color[0];
7764 c[1] = layer->color[1];
7765 c[2] = layer->color[2];
7766 c[3] = f * layer->color[3];
7769 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7772 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7774 GL_LockArrays(0, 0);
7777 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7779 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7780 GL_AlphaTest(false);
7784 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7788 GL_AlphaTest(false);
7789 R_Mesh_ColorPointer(NULL, 0, 0);
7790 R_Mesh_ResetTextureState();
7791 R_SetupGenericShader(false);
7793 if(rsurface.texture && rsurface.texture->currentskinframe)
7795 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7796 c[3] *= rsurface.texture->currentalpha;
7806 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7808 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7809 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7810 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7813 // brighten it up (as texture value 127 means "unlit")
7814 c[0] *= 2 * r_refdef.view.colorscale;
7815 c[1] *= 2 * r_refdef.view.colorscale;
7816 c[2] *= 2 * r_refdef.view.colorscale;
7818 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7819 c[3] *= r_wateralpha.value;
7821 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7823 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7824 GL_DepthMask(false);
7826 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7828 GL_BlendFunc(GL_ONE, GL_ONE);
7829 GL_DepthMask(false);
7831 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7833 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7834 GL_DepthMask(false);
7836 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7838 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7839 GL_DepthMask(false);
7843 GL_BlendFunc(GL_ONE, GL_ZERO);
7844 GL_DepthMask(writedepth);
7847 rsurface.lightmapcolor4f = NULL;
7849 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7851 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7853 rsurface.lightmapcolor4f = NULL;
7854 rsurface.lightmapcolor4f_bufferobject = 0;
7855 rsurface.lightmapcolor4f_bufferoffset = 0;
7857 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7859 qboolean applycolor = true;
7862 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7864 r_refdef.lightmapintensity = 1;
7865 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7866 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7870 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7872 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7873 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7874 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7877 if(!rsurface.lightmapcolor4f)
7878 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7880 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7881 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7882 if(r_refdef.fogenabled)
7883 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7885 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7886 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7889 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7892 RSurf_SetupDepthAndCulling();
7893 if (r_showsurfaces.integer == 3)
7894 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7895 else if (r_glsl.integer && vid.support.arb_fragment_shader)
7896 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7897 else if (gl_combine.integer && r_textureunits.integer >= 2)
7898 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7900 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7904 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7907 RSurf_SetupDepthAndCulling();
7908 if (r_showsurfaces.integer == 3)
7909 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7910 else if (r_glsl.integer && vid.support.arb_fragment_shader)
7911 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7912 else if (gl_combine.integer && r_textureunits.integer >= 2)
7913 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7915 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7919 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7922 int texturenumsurfaces, endsurface;
7924 const msurface_t *surface;
7925 const msurface_t *texturesurfacelist[1024];
7927 // if the model is static it doesn't matter what value we give for
7928 // wantnormals and wanttangents, so this logic uses only rules applicable
7929 // to a model, knowing that they are meaningless otherwise
7930 if (ent == r_refdef.scene.worldentity)
7931 RSurf_ActiveWorldEntity();
7932 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7933 RSurf_ActiveModelEntity(ent, false, false);
7935 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && vid.support.arb_fragment_shader);
7937 for (i = 0;i < numsurfaces;i = j)
7940 surface = rsurface.modelsurfaces + surfacelist[i];
7941 texture = surface->texture;
7942 rsurface.texture = R_GetCurrentTexture(texture);
7943 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7944 // scan ahead until we find a different texture
7945 endsurface = min(i + 1024, numsurfaces);
7946 texturenumsurfaces = 0;
7947 texturesurfacelist[texturenumsurfaces++] = surface;
7948 for (;j < endsurface;j++)
7950 surface = rsurface.modelsurfaces + surfacelist[j];
7951 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7953 texturesurfacelist[texturenumsurfaces++] = surface;
7955 // render the range of surfaces
7956 if (ent == r_refdef.scene.worldentity)
7957 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7959 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7961 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7962 GL_AlphaTest(false);
7965 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7967 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7971 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7973 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7975 RSurf_SetupDepthAndCulling();
7976 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7977 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7979 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7981 RSurf_SetupDepthAndCulling();
7982 GL_AlphaTest(false);
7983 R_Mesh_ColorPointer(NULL, 0, 0);
7984 R_Mesh_ResetTextureState();
7985 R_SetupGenericShader(false);
7986 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7988 GL_BlendFunc(GL_ONE, GL_ZERO);
7989 GL_Color(0, 0, 0, 1);
7990 GL_DepthTest(writedepth);
7991 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7993 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7995 RSurf_SetupDepthAndCulling();
7996 GL_AlphaTest(false);
7997 R_Mesh_ColorPointer(NULL, 0, 0);
7998 R_Mesh_ResetTextureState();
7999 R_SetupGenericShader(false);
8000 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8002 GL_BlendFunc(GL_ONE, GL_ZERO);
8004 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8006 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8007 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8008 else if (!rsurface.texture->currentnumlayers)
8010 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8012 // transparent surfaces get pushed off into the transparent queue
8013 int surfacelistindex;
8014 const msurface_t *surface;
8015 vec3_t tempcenter, center;
8016 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8018 surface = texturesurfacelist[surfacelistindex];
8019 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8020 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8021 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8022 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8023 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8028 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8029 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8034 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8038 // break the surface list down into batches by texture and use of lightmapping
8039 for (i = 0;i < numsurfaces;i = j)
8042 // texture is the base texture pointer, rsurface.texture is the
8043 // current frame/skin the texture is directing us to use (for example
8044 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8045 // use skin 1 instead)
8046 texture = surfacelist[i]->texture;
8047 rsurface.texture = R_GetCurrentTexture(texture);
8048 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8049 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8051 // if this texture is not the kind we want, skip ahead to the next one
8052 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8056 // simply scan ahead until we find a different texture or lightmap state
8057 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8059 // render the range of surfaces
8060 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
8064 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
8069 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8071 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8073 RSurf_SetupDepthAndCulling();
8074 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8075 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8077 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8079 RSurf_SetupDepthAndCulling();
8080 GL_AlphaTest(false);
8081 R_Mesh_ColorPointer(NULL, 0, 0);
8082 R_Mesh_ResetTextureState();
8083 R_SetupGenericShader(false);
8084 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8086 GL_BlendFunc(GL_ONE, GL_ZERO);
8087 GL_Color(0, 0, 0, 1);
8088 GL_DepthTest(writedepth);
8089 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8091 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8093 RSurf_SetupDepthAndCulling();
8094 GL_AlphaTest(false);
8095 R_Mesh_ColorPointer(NULL, 0, 0);
8096 R_Mesh_ResetTextureState();
8097 R_SetupGenericShader(false);
8098 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8100 GL_BlendFunc(GL_ONE, GL_ZERO);
8102 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8104 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8105 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8106 else if (!rsurface.texture->currentnumlayers)
8108 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8110 // transparent surfaces get pushed off into the transparent queue
8111 int surfacelistindex;
8112 const msurface_t *surface;
8113 vec3_t tempcenter, center;
8114 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8116 surface = texturesurfacelist[surfacelistindex];
8117 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8118 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8119 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8120 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8121 if (queueentity->transparent_offset) // transparent offset
8123 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8124 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8125 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8127 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8132 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8133 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8138 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8142 // break the surface list down into batches by texture and use of lightmapping
8143 for (i = 0;i < numsurfaces;i = j)
8146 // texture is the base texture pointer, rsurface.texture is the
8147 // current frame/skin the texture is directing us to use (for example
8148 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8149 // use skin 1 instead)
8150 texture = surfacelist[i]->texture;
8151 rsurface.texture = R_GetCurrentTexture(texture);
8152 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8153 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8155 // if this texture is not the kind we want, skip ahead to the next one
8156 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8160 // simply scan ahead until we find a different texture or lightmap state
8161 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8163 // render the range of surfaces
8164 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8168 float locboxvertex3f[6*4*3] =
8170 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8171 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8172 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8173 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8174 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8175 1,0,0, 0,0,0, 0,1,0, 1,1,0
8178 unsigned short locboxelements[6*2*3] =
8188 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8191 cl_locnode_t *loc = (cl_locnode_t *)ent;
8193 float vertex3f[6*4*3];
8195 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8196 GL_DepthMask(false);
8197 GL_DepthRange(0, 1);
8198 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8200 GL_CullFace(GL_NONE);
8201 R_Mesh_Matrix(&identitymatrix);
8203 R_Mesh_VertexPointer(vertex3f, 0, 0);
8204 R_Mesh_ColorPointer(NULL, 0, 0);
8205 R_Mesh_ResetTextureState();
8206 R_SetupGenericShader(false);
8209 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8210 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8211 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8212 surfacelist[0] < 0 ? 0.5f : 0.125f);
8214 if (VectorCompare(loc->mins, loc->maxs))
8216 VectorSet(size, 2, 2, 2);
8217 VectorMA(loc->mins, -0.5f, size, mins);
8221 VectorCopy(loc->mins, mins);
8222 VectorSubtract(loc->maxs, loc->mins, size);
8225 for (i = 0;i < 6*4*3;)
8226 for (j = 0;j < 3;j++, i++)
8227 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8229 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8232 void R_DrawLocs(void)
8235 cl_locnode_t *loc, *nearestloc;
8237 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8238 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8240 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8241 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8245 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8247 if (decalsystem->decals)
8248 Mem_Free(decalsystem->decals);
8249 memset(decalsystem, 0, sizeof(*decalsystem));
8252 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)
8259 // expand or initialize the system
8260 if (decalsystem->maxdecals <= decalsystem->numdecals)
8262 decalsystem_t old = *decalsystem;
8263 qboolean useshortelements;
8264 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8265 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8266 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)));
8267 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8268 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8269 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8270 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8271 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8272 if (decalsystem->numdecals)
8273 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8275 Mem_Free(old.decals);
8276 for (i = 0;i < decalsystem->maxdecals*3;i++)
8277 decalsystem->element3i[i] = i;
8278 if (useshortelements)
8279 for (i = 0;i < decalsystem->maxdecals*3;i++)
8280 decalsystem->element3s[i] = i;
8283 // grab a decal and search for another free slot for the next one
8284 maxdecals = decalsystem->maxdecals;
8285 decals = decalsystem->decals;
8286 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8287 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8289 decalsystem->freedecal = i;
8290 if (decalsystem->numdecals <= i)
8291 decalsystem->numdecals = i + 1;
8293 // initialize the decal
8295 decal->triangleindex = triangleindex;
8296 decal->surfaceindex = surfaceindex;
8297 decal->decalsequence = decalsequence;
8298 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8299 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8300 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8301 decal->color4ub[0][3] = 255;
8302 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8303 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8304 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8305 decal->color4ub[1][3] = 255;
8306 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8307 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8308 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8309 decal->color4ub[2][3] = 255;
8310 decal->vertex3f[0][0] = v0[0];
8311 decal->vertex3f[0][1] = v0[1];
8312 decal->vertex3f[0][2] = v0[2];
8313 decal->vertex3f[1][0] = v1[0];
8314 decal->vertex3f[1][1] = v1[1];
8315 decal->vertex3f[1][2] = v1[2];
8316 decal->vertex3f[2][0] = v2[0];
8317 decal->vertex3f[2][1] = v2[1];
8318 decal->vertex3f[2][2] = v2[2];
8319 decal->texcoord2f[0][0] = t0[0];
8320 decal->texcoord2f[0][1] = t0[1];
8321 decal->texcoord2f[1][0] = t1[0];
8322 decal->texcoord2f[1][1] = t1[1];
8323 decal->texcoord2f[2][0] = t2[0];
8324 decal->texcoord2f[2][1] = t2[1];
8327 extern cvar_t cl_decals_bias;
8328 extern cvar_t cl_decals_models;
8329 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8330 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)
8332 matrix4x4_t projection;
8333 decalsystem_t *decalsystem;
8336 const float *vertex3f;
8337 const msurface_t *surface;
8338 const msurface_t *surfaces;
8339 const int *surfacelist;
8340 const texture_t *texture;
8344 int surfacelistindex;
8347 int decalsurfaceindex;
8352 float localorigin[3];
8353 float localnormal[3];
8364 float points[2][9][3];
8368 decalsystem = &ent->decalsystem;
8370 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8372 R_DecalSystem_Reset(&ent->decalsystem);
8376 if (!model->brush.data_nodes && !cl_decals_models.integer)
8378 if (decalsystem->model)
8379 R_DecalSystem_Reset(decalsystem);
8383 if (decalsystem->model != model)
8384 R_DecalSystem_Reset(decalsystem);
8385 decalsystem->model = model;
8387 RSurf_ActiveModelEntity(ent, false, false);
8389 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8390 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8391 VectorNormalize(localnormal);
8392 localsize = worldsize*rsurface.inversematrixscale;
8393 ilocalsize = 1.0f / localsize;
8394 localmins[0] = localorigin[0] - localsize;
8395 localmins[1] = localorigin[1] - localsize;
8396 localmins[2] = localorigin[2] - localsize;
8397 localmaxs[0] = localorigin[0] + localsize;
8398 localmaxs[1] = localorigin[1] + localsize;
8399 localmaxs[2] = localorigin[2] + localsize;
8401 //VectorCopy(localnormal, planes[4]);
8402 //VectorVectors(planes[4], planes[2], planes[0]);
8403 AnglesFromVectors(angles, localnormal, NULL, false);
8404 AngleVectors(angles, planes[0], planes[2], planes[4]);
8405 VectorNegate(planes[0], planes[1]);
8406 VectorNegate(planes[2], planes[3]);
8407 VectorNegate(planes[4], planes[5]);
8408 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8409 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8410 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8411 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8412 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8413 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8418 matrix4x4_t forwardprojection;
8419 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8420 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8425 float projectionvector[4][3];
8426 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8427 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8428 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8429 projectionvector[0][0] = planes[0][0] * ilocalsize;
8430 projectionvector[0][1] = planes[1][0] * ilocalsize;
8431 projectionvector[0][2] = planes[2][0] * ilocalsize;
8432 projectionvector[1][0] = planes[0][1] * ilocalsize;
8433 projectionvector[1][1] = planes[1][1] * ilocalsize;
8434 projectionvector[1][2] = planes[2][1] * ilocalsize;
8435 projectionvector[2][0] = planes[0][2] * ilocalsize;
8436 projectionvector[2][1] = planes[1][2] * ilocalsize;
8437 projectionvector[2][2] = planes[2][2] * ilocalsize;
8438 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8439 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8440 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8441 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8445 dynamic = model->surfmesh.isanimated;
8446 vertex3f = rsurface.modelvertex3f;
8447 numsurfacelist = model->nummodelsurfaces;
8448 surfacelist = model->sortedmodelsurfaces;
8449 surfaces = model->data_surfaces;
8450 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8452 surfaceindex = surfacelist[surfacelistindex];
8453 surface = surfaces + surfaceindex;
8454 // skip transparent surfaces
8455 texture = surface->texture;
8456 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8458 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8460 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8462 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8463 numvertices = surface->num_vertices;
8464 numtriangles = surface->num_triangles;
8465 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8467 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8469 index = 3*e[cornerindex];
8470 VectorCopy(vertex3f + index, v[cornerindex]);
8473 //TriangleNormal(v[0], v[1], v[2], normal);
8474 //if (DotProduct(normal, localnormal) < 0.0f)
8476 // clip by each of the box planes formed from the projection matrix
8477 // if anything survives, we emit the decal
8478 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]);
8481 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]);
8484 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]);
8487 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]);
8490 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]);
8493 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]);
8496 // some part of the triangle survived, so we have to accept it...
8499 // dynamic always uses the original triangle
8501 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8503 index = 3*e[cornerindex];
8504 VectorCopy(vertex3f + index, v[cornerindex]);
8507 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8509 // convert vertex positions to texcoords
8510 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8511 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8512 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8513 // calculate distance fade from the projection origin
8514 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8515 f = bound(0.0f, f, 1.0f);
8516 c[cornerindex][0] = r * f;
8517 c[cornerindex][1] = g * f;
8518 c[cornerindex][2] = b * f;
8519 c[cornerindex][3] = 1.0f;
8520 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8523 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);
8525 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8526 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);
8531 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8532 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)
8534 int renderentityindex;
8537 entity_render_t *ent;
8539 if (!cl_decals_newsystem.integer)
8542 worldmins[0] = worldorigin[0] - worldsize;
8543 worldmins[1] = worldorigin[1] - worldsize;
8544 worldmins[2] = worldorigin[2] - worldsize;
8545 worldmaxs[0] = worldorigin[0] + worldsize;
8546 worldmaxs[1] = worldorigin[1] + worldsize;
8547 worldmaxs[2] = worldorigin[2] + worldsize;
8549 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8551 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8553 ent = r_refdef.scene.entities[renderentityindex];
8554 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8557 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8561 typedef struct r_decalsystem_splatqueue_s
8570 r_decalsystem_splatqueue_t;
8572 int r_decalsystem_numqueued = 0;
8573 #define MAX_DECALSYSTEM_QUEUE 1024
8574 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8576 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)
8578 r_decalsystem_splatqueue_t *queue;
8580 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8583 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8584 VectorCopy(worldorigin, queue->worldorigin);
8585 VectorCopy(worldnormal, queue->worldnormal);
8586 Vector4Set(queue->color, r, g, b, a);
8587 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8588 queue->worldsize = worldsize;
8589 queue->decalsequence = cl.decalsequence++;
8592 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8595 r_decalsystem_splatqueue_t *queue;
8597 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8598 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);
8599 r_decalsystem_numqueued = 0;
8602 extern cvar_t cl_decals_max;
8603 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8606 decalsystem_t *decalsystem = &ent->decalsystem;
8613 if (!decalsystem->numdecals)
8616 if (r_showsurfaces.integer)
8619 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8621 R_DecalSystem_Reset(decalsystem);
8625 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
8626 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
8628 if (decalsystem->lastupdatetime)
8629 frametime = (cl.time - decalsystem->lastupdatetime);
8632 decalsystem->lastupdatetime = cl.time;
8633 decal = decalsystem->decals;
8634 numdecals = decalsystem->numdecals;
8636 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8638 if (decal->color4ub[0][3])
8640 decal->lived += frametime;
8641 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
8643 memset(decal, 0, sizeof(*decal));
8644 if (decalsystem->freedecal > i)
8645 decalsystem->freedecal = i;
8649 decal = decalsystem->decals;
8650 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
8653 // collapse the array by shuffling the tail decals into the gaps
8656 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
8657 decalsystem->freedecal++;
8658 if (decalsystem->freedecal == numdecals)
8660 decal[decalsystem->freedecal] = decal[--numdecals];
8663 decalsystem->numdecals = numdecals;
8667 // if there are no decals left, reset decalsystem
8668 R_DecalSystem_Reset(decalsystem);
8672 extern skinframe_t *decalskinframe;
8673 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8676 decalsystem_t *decalsystem = &ent->decalsystem;
8686 const unsigned char *surfacevisible = r_refdef.viewcache.world_surfacevisible;
8689 numdecals = decalsystem->numdecals;
8693 if (r_showsurfaces.integer)
8696 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8698 R_DecalSystem_Reset(decalsystem);
8702 // if the model is static it doesn't matter what value we give for
8703 // wantnormals and wanttangents, so this logic uses only rules applicable
8704 // to a model, knowing that they are meaningless otherwise
8705 if (ent == r_refdef.scene.worldentity)
8706 RSurf_ActiveWorldEntity();
8708 RSurf_ActiveModelEntity(ent, false, false);
8710 decalsystem->lastupdatetime = cl.time;
8711 decal = decalsystem->decals;
8713 fadedelay = cl_decals_time.value;
8714 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
8716 // update vertex positions for animated models
8717 v3f = decalsystem->vertex3f;
8718 c4f = decalsystem->color4f;
8719 t2f = decalsystem->texcoord2f;
8720 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8722 if (!decal->color4ub[0][3])
8725 if (decal->surfaceindex >= 0 && !surfacevisible[decal->surfaceindex])
8728 // update color values for fading decals
8729 if (decal->lived >= cl_decals_time.value)
8731 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
8732 alpha *= (1.0f/255.0f);
8735 alpha = 1.0f/255.0f;
8737 c4f[ 0] = decal->color4ub[0][0] * alpha;
8738 c4f[ 1] = decal->color4ub[0][1] * alpha;
8739 c4f[ 2] = decal->color4ub[0][2] * alpha;
8741 c4f[ 4] = decal->color4ub[1][0] * alpha;
8742 c4f[ 5] = decal->color4ub[1][1] * alpha;
8743 c4f[ 6] = decal->color4ub[1][2] * alpha;
8745 c4f[ 8] = decal->color4ub[2][0] * alpha;
8746 c4f[ 9] = decal->color4ub[2][1] * alpha;
8747 c4f[10] = decal->color4ub[2][2] * alpha;
8750 t2f[0] = decal->texcoord2f[0][0];
8751 t2f[1] = decal->texcoord2f[0][1];
8752 t2f[2] = decal->texcoord2f[1][0];
8753 t2f[3] = decal->texcoord2f[1][1];
8754 t2f[4] = decal->texcoord2f[2][0];
8755 t2f[5] = decal->texcoord2f[2][1];
8757 // update vertex positions for animated models
8758 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8760 e = rsurface.modelelement3i + 3*decal->triangleindex;
8761 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8762 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8763 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8767 VectorCopy(decal->vertex3f[0], v3f);
8768 VectorCopy(decal->vertex3f[1], v3f + 3);
8769 VectorCopy(decal->vertex3f[2], v3f + 6);
8780 r_refdef.stats.drawndecals += numtris;
8781 // now render the decals all at once
8782 // (this assumes they all use one particle font texture!)
8783 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);
8784 R_Mesh_ResetTextureState();
8785 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8786 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8787 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8788 R_SetupGenericShader(true);
8789 GL_DepthMask(false);
8790 GL_DepthRange(0, 1);
8791 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
8793 GL_CullFace(GL_NONE);
8794 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8795 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8796 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8797 GL_LockArrays(0, numtris * 3);
8798 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
8799 GL_LockArrays(0, 0);
8803 static void R_DrawModelDecals(void)
8807 // fade faster when there are too many decals
8808 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
8809 for (i = 0;i < r_refdef.scene.numentities;i++)
8810 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
8812 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
8813 for (i = 0;i < r_refdef.scene.numentities;i++)
8814 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
8815 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
8817 R_DecalSystem_ApplySplatEntitiesQueue();
8819 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
8820 for (i = 0;i < r_refdef.scene.numentities;i++)
8821 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
8823 r_refdef.stats.totaldecals += numdecals;
8825 if (r_showsurfaces.integer)
8828 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
8830 if (!r_drawentities.integer)
8833 for (i = 0;i < r_refdef.scene.numentities;i++)
8835 if (!r_refdef.viewcache.entityvisible[i])
8837 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
8838 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
8842 void R_DrawDebugModel(void)
8844 entity_render_t *ent = rsurface.entity;
8845 int i, j, k, l, flagsmask;
8846 const int *elements;
8848 const msurface_t *surface;
8849 dp_model_t *model = ent->model;
8852 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8854 R_Mesh_ColorPointer(NULL, 0, 0);
8855 R_Mesh_ResetTextureState();
8856 R_SetupGenericShader(false);
8857 GL_DepthRange(0, 1);
8858 GL_DepthTest(!r_showdisabledepthtest.integer);
8859 GL_DepthMask(false);
8860 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8862 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8864 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8865 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8867 if (brush->colbrushf && brush->colbrushf->numtriangles)
8869 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8870 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);
8871 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8874 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8876 if (surface->num_collisiontriangles)
8878 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8879 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);
8880 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8885 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8887 if (r_showtris.integer || r_shownormals.integer)
8889 if (r_showdisabledepthtest.integer)
8891 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8892 GL_DepthMask(false);
8896 GL_BlendFunc(GL_ONE, GL_ZERO);
8899 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8901 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8903 rsurface.texture = R_GetCurrentTexture(surface->texture);
8904 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8906 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8907 if (r_showtris.value > 0)
8909 if (!rsurface.texture->currentlayers->depthmask)
8910 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8911 else if (ent == r_refdef.scene.worldentity)
8912 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8914 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8915 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8916 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8917 R_Mesh_ColorPointer(NULL, 0, 0);
8918 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8919 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8920 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8921 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);
8922 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8925 if (r_shownormals.value < 0)
8928 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8930 VectorCopy(rsurface.vertex3f + l * 3, v);
8931 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8932 qglVertex3f(v[0], v[1], v[2]);
8933 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8934 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8935 qglVertex3f(v[0], v[1], v[2]);
8940 if (r_shownormals.value > 0)
8943 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8945 VectorCopy(rsurface.vertex3f + l * 3, v);
8946 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8947 qglVertex3f(v[0], v[1], v[2]);
8948 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8949 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8950 qglVertex3f(v[0], v[1], v[2]);
8955 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8957 VectorCopy(rsurface.vertex3f + l * 3, v);
8958 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8959 qglVertex3f(v[0], v[1], v[2]);
8960 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8961 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8962 qglVertex3f(v[0], v[1], v[2]);
8967 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8969 VectorCopy(rsurface.vertex3f + l * 3, v);
8970 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8971 qglVertex3f(v[0], v[1], v[2]);
8972 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8973 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8974 qglVertex3f(v[0], v[1], v[2]);
8981 rsurface.texture = NULL;
8985 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8986 int r_maxsurfacelist = 0;
8987 const msurface_t **r_surfacelist = NULL;
8988 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8990 int i, j, endj, f, flagsmask;
8992 dp_model_t *model = r_refdef.scene.worldmodel;
8993 msurface_t *surfaces;
8994 unsigned char *update;
8995 int numsurfacelist = 0;
8999 if (r_maxsurfacelist < model->num_surfaces)
9001 r_maxsurfacelist = model->num_surfaces;
9003 Mem_Free((msurface_t**)r_surfacelist);
9004 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9007 RSurf_ActiveWorldEntity();
9009 surfaces = model->data_surfaces;
9010 update = model->brushq1.lightmapupdateflags;
9012 // update light styles on this submodel
9013 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9015 model_brush_lightstyleinfo_t *style;
9016 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9018 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9020 int *list = style->surfacelist;
9021 style->value = r_refdef.scene.lightstylevalue[style->style];
9022 for (j = 0;j < style->numsurfaces;j++)
9023 update[list[j]] = true;
9028 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9033 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9039 rsurface.uselightmaptexture = false;
9040 rsurface.texture = NULL;
9041 rsurface.rtlight = NULL;
9043 // add visible surfaces to draw list
9044 for (i = 0;i < model->nummodelsurfaces;i++)
9046 j = model->sortedmodelsurfaces[i];
9047 if (r_refdef.viewcache.world_surfacevisible[j])
9048 r_surfacelist[numsurfacelist++] = surfaces + j;
9050 // update lightmaps if needed
9052 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9053 if (r_refdef.viewcache.world_surfacevisible[j])
9055 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9056 // don't do anything if there were no surfaces
9057 if (!numsurfacelist)
9059 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9062 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
9063 GL_AlphaTest(false);
9065 // add to stats if desired
9066 if (r_speeds.integer && !skysurfaces && !depthonly)
9068 r_refdef.stats.world_surfaces += numsurfacelist;
9069 for (j = 0;j < numsurfacelist;j++)
9070 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9073 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9076 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
9078 int i, j, endj, f, flagsmask;
9080 dp_model_t *model = ent->model;
9081 msurface_t *surfaces;
9082 unsigned char *update;
9083 int numsurfacelist = 0;
9087 if (r_maxsurfacelist < model->num_surfaces)
9089 r_maxsurfacelist = model->num_surfaces;
9091 Mem_Free((msurface_t **)r_surfacelist);
9092 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9095 // if the model is static it doesn't matter what value we give for
9096 // wantnormals and wanttangents, so this logic uses only rules applicable
9097 // to a model, knowing that they are meaningless otherwise
9098 if (ent == r_refdef.scene.worldentity)
9099 RSurf_ActiveWorldEntity();
9100 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9101 RSurf_ActiveModelEntity(ent, false, false);
9103 RSurf_ActiveModelEntity(ent, false, false);
9105 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && vid.support.arb_fragment_shader);
9107 surfaces = model->data_surfaces;
9108 update = model->brushq1.lightmapupdateflags;
9110 // update light styles
9111 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9113 model_brush_lightstyleinfo_t *style;
9114 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9116 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9118 int *list = style->surfacelist;
9119 style->value = r_refdef.scene.lightstylevalue[style->style];
9120 for (j = 0;j < style->numsurfaces;j++)
9121 update[list[j]] = true;
9126 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9131 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9137 rsurface.uselightmaptexture = false;
9138 rsurface.texture = NULL;
9139 rsurface.rtlight = NULL;
9141 // add visible surfaces to draw list
9142 for (i = 0;i < model->nummodelsurfaces;i++)
9143 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9144 // don't do anything if there were no surfaces
9145 if (!numsurfacelist)
9147 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9150 // update lightmaps if needed
9152 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9154 R_BuildLightMap(ent, surfaces + j);
9155 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
9156 GL_AlphaTest(false);
9158 // add to stats if desired
9159 if (r_speeds.integer && !skysurfaces && !depthonly)
9161 r_refdef.stats.entities_surfaces += numsurfacelist;
9162 for (j = 0;j < numsurfacelist;j++)
9163 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9166 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9169 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
9171 static texture_t texture;
9172 static msurface_t surface;
9173 const msurface_t *surfacelist = &surface;
9175 // fake enough texture and surface state to render this geometry
9177 texture.update_lastrenderframe = -1; // regenerate this texture
9178 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9179 texture.currentskinframe = skinframe;
9180 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9181 texture.specularscalemod = 1;
9182 texture.specularpowermod = 1;
9184 surface.texture = &texture;
9185 surface.num_triangles = numtriangles;
9186 surface.num_firsttriangle = firsttriangle;
9187 surface.num_vertices = numvertices;
9188 surface.num_firstvertex = firstvertex;
9191 rsurface.texture = R_GetCurrentTexture(surface.texture);
9192 rsurface.uselightmaptexture = false;
9193 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);