2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
38 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
47 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
48 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
49 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
50 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
51 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
53 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
55 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
56 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
57 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
58 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
59 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
60 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
61 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
62 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
63 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
64 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
65 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
66 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
67 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
68 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
69 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
70 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
71 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
72 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
73 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
74 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
75 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)"};
76 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
77 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
78 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
79 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
80 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
81 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
82 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
83 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."};
84 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
85 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
86 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
87 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."};
88 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
89 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
90 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"};
91 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"};
92 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
93 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
94 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
95 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
97 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
98 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
99 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
100 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
101 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
102 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
103 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
104 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
106 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)"};
108 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
109 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)"};
110 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
111 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
112 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
113 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
114 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)"};
115 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)"};
116 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)"};
117 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)"};
118 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
120 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)"};
121 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
122 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"};
123 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
124 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
126 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
127 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
128 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
129 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
131 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
132 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
133 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
134 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
135 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
136 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
137 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
139 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
140 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
141 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
142 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)"};
144 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"};
146 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"};
148 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
150 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
151 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
152 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"};
153 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
154 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
155 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
156 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
158 extern cvar_t v_glslgamma;
160 extern qboolean v_flipped_state;
162 static struct r_bloomstate_s
167 int bloomwidth, bloomheight;
169 int screentexturewidth, screentextureheight;
170 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
172 int bloomtexturewidth, bloomtextureheight;
173 rtexture_t *texture_bloom;
175 // arrays for rendering the screen passes
176 float screentexcoord2f[8];
177 float bloomtexcoord2f[8];
178 float offsettexcoord2f[8];
180 r_viewport_t viewport;
184 r_waterstate_t r_waterstate;
186 /// shadow volume bsp struct with automatically growing nodes buffer
189 rtexture_t *r_texture_blanknormalmap;
190 rtexture_t *r_texture_white;
191 rtexture_t *r_texture_grey128;
192 rtexture_t *r_texture_black;
193 rtexture_t *r_texture_notexture;
194 rtexture_t *r_texture_whitecube;
195 rtexture_t *r_texture_normalizationcube;
196 rtexture_t *r_texture_fogattenuation;
197 rtexture_t *r_texture_gammaramps;
198 unsigned int r_texture_gammaramps_serial;
199 //rtexture_t *r_texture_fogintensity;
201 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
202 unsigned int r_numqueries;
203 unsigned int r_maxqueries;
205 typedef struct r_qwskincache_s
207 char name[MAX_QPATH];
208 skinframe_t *skinframe;
212 static r_qwskincache_t *r_qwskincache;
213 static int r_qwskincache_size;
215 /// vertex coordinates for a quad that covers the screen exactly
216 const float r_screenvertex3f[12] =
224 extern void R_DrawModelShadows(void);
226 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
229 for (i = 0;i < verts;i++)
240 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
243 for (i = 0;i < verts;i++)
253 // FIXME: move this to client?
256 if (gamemode == GAME_NEHAHRA)
258 Cvar_Set("gl_fogenable", "0");
259 Cvar_Set("gl_fogdensity", "0.2");
260 Cvar_Set("gl_fogred", "0.3");
261 Cvar_Set("gl_foggreen", "0.3");
262 Cvar_Set("gl_fogblue", "0.3");
264 r_refdef.fog_density = 0;
265 r_refdef.fog_red = 0;
266 r_refdef.fog_green = 0;
267 r_refdef.fog_blue = 0;
268 r_refdef.fog_alpha = 1;
269 r_refdef.fog_start = 0;
270 r_refdef.fog_end = 16384;
271 r_refdef.fog_height = 1<<30;
272 r_refdef.fog_fadedepth = 128;
275 static void R_BuildBlankTextures(void)
277 unsigned char data[4];
278 data[2] = 128; // normal X
279 data[1] = 128; // normal Y
280 data[0] = 255; // normal Z
281 data[3] = 128; // height
282 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
287 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
292 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
297 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
300 static void R_BuildNoTexture(void)
303 unsigned char pix[16][16][4];
304 // this makes a light grey/dark grey checkerboard texture
305 for (y = 0;y < 16;y++)
307 for (x = 0;x < 16;x++)
309 if ((y < 8) ^ (x < 8))
325 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
328 static void R_BuildWhiteCube(void)
330 unsigned char data[6*1*1*4];
331 memset(data, 255, sizeof(data));
332 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
335 static void R_BuildNormalizationCube(void)
339 vec_t s, t, intensity;
341 unsigned char data[6][NORMSIZE][NORMSIZE][4];
342 for (side = 0;side < 6;side++)
344 for (y = 0;y < NORMSIZE;y++)
346 for (x = 0;x < NORMSIZE;x++)
348 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
349 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
384 intensity = 127.0f / sqrt(DotProduct(v, v));
385 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
386 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
387 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
388 data[side][y][x][3] = 255;
392 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
395 static void R_BuildFogTexture(void)
399 unsigned char data1[FOGWIDTH][4];
400 //unsigned char data2[FOGWIDTH][4];
403 r_refdef.fogmasktable_start = r_refdef.fog_start;
404 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
405 r_refdef.fogmasktable_range = r_refdef.fogrange;
406 r_refdef.fogmasktable_density = r_refdef.fog_density;
408 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
409 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
411 d = (x * r - r_refdef.fogmasktable_start);
412 if(developer.integer >= 100)
413 Con_Printf("%f ", d);
415 if (r_fog_exp2.integer)
416 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
418 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
419 if(developer.integer >= 100)
420 Con_Printf(" : %f ", alpha);
421 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
422 if(developer.integer >= 100)
423 Con_Printf(" = %f\n", alpha);
424 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
427 for (x = 0;x < FOGWIDTH;x++)
429 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
434 //data2[x][0] = 255 - b;
435 //data2[x][1] = 255 - b;
436 //data2[x][2] = 255 - b;
439 if (r_texture_fogattenuation)
441 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
442 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
446 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);
447 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
451 static const char *builtinshaderstring =
452 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
453 "// written by Forest 'LordHavoc' Hale\n"
455 "// enable various extensions depending on permutation:\n"
457 "#ifdef USESHADOWMAPRECT\n"
458 "# extension GL_ARB_texture_rectangle : enable\n"
461 "#ifdef USESHADOWMAP2D\n"
462 "# ifdef GL_EXT_gpu_shader4\n"
463 "# extension GL_EXT_gpu_shader4 : enable\n"
465 "# ifdef GL_ARB_texture_gather\n"
466 "# extension GL_ARB_texture_gather : enable\n"
468 "# ifdef GL_AMD_texture_texture4\n"
469 "# extension GL_AMD_texture_texture4 : enable\n"
474 "#ifdef USESHADOWMAPCUBE\n"
475 "# extension GL_EXT_gpu_shader4 : enable\n"
478 "#ifdef USESHADOWSAMPLER\n"
479 "# extension GL_ARB_shadow : enable\n"
482 "// common definitions between vertex shader and fragment shader:\n"
484 "//#ifdef __GLSL_CG_DATA_TYPES\n"
485 "//# define myhalf half\n"
486 "//# define myhalf2 half2\n"
487 "//# define myhalf3half3\n"
488 "//# define myhalf4 half4\n"
490 "# define myhalf float\n"
491 "# define myhalf2 vec2\n"
492 "# define myhalf3 vec3\n"
493 "# define myhalf4 vec4\n"
496 "#ifdef USEFOGINSIDE\n"
499 "# ifdef USEFOGOUTSIDE\n"
504 "#ifdef MODE_DEPTH_OR_SHADOW\n"
506 "# ifdef VERTEX_SHADER\n"
509 " gl_Position = ftransform();\n"
514 "#ifdef MODE_SHOWDEPTH\n"
515 "# ifdef VERTEX_SHADER\n"
518 " gl_Position = ftransform();\n"
519 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
522 "# ifdef FRAGMENT_SHADER\n"
525 " gl_FragColor = gl_Color;\n"
529 "#else // !MODE_SHOWDEPTH\n"
531 "#ifdef MODE_POSTPROCESS\n"
532 "# ifdef VERTEX_SHADER\n"
535 " gl_FrontColor = gl_Color;\n"
536 " gl_Position = ftransform();\n"
537 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
539 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
543 "# ifdef FRAGMENT_SHADER\n"
545 "uniform sampler2D Texture_First;\n"
547 "uniform sampler2D Texture_Second;\n"
549 "#ifdef USEGAMMARAMPS\n"
550 "uniform sampler2D Texture_GammaRamps;\n"
552 "#ifdef USESATURATION\n"
553 "uniform float Saturation;\n"
555 "#ifdef USEVIEWTINT\n"
556 "uniform vec4 TintColor;\n"
558 "//uncomment these if you want to use them:\n"
559 "uniform vec4 UserVec1;\n"
560 "// uniform vec4 UserVec2;\n"
561 "// uniform vec4 UserVec3;\n"
562 "// uniform vec4 UserVec4;\n"
563 "// uniform float ClientTime;\n"
564 "uniform vec2 PixelSize;\n"
567 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
569 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
571 "#ifdef USEVIEWTINT\n"
572 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
575 "#ifdef USEPOSTPROCESSING\n"
576 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
577 "// 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"
578 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
579 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
580 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
581 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
582 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
583 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
586 "#ifdef USESATURATION\n"
587 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
588 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
589 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
590 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
593 "#ifdef USEGAMMARAMPS\n"
594 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
595 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
596 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
603 "#ifdef MODE_GENERIC\n"
604 "# ifdef VERTEX_SHADER\n"
607 " gl_FrontColor = gl_Color;\n"
608 "# ifdef USEDIFFUSE\n"
609 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
611 "# ifdef USESPECULAR\n"
612 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
614 " gl_Position = ftransform();\n"
617 "# ifdef FRAGMENT_SHADER\n"
619 "# ifdef USEDIFFUSE\n"
620 "uniform sampler2D Texture_First;\n"
622 "# ifdef USESPECULAR\n"
623 "uniform sampler2D Texture_Second;\n"
628 " gl_FragColor = gl_Color;\n"
629 "# ifdef USEDIFFUSE\n"
630 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
633 "# ifdef USESPECULAR\n"
634 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
636 "# ifdef USECOLORMAPPING\n"
637 " gl_FragColor *= tex2;\n"
640 " gl_FragColor += tex2;\n"
642 "# ifdef USEVERTEXTEXTUREBLEND\n"
643 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
648 "#else // !MODE_GENERIC\n"
649 "#ifdef MODE_BLOOMBLUR\n"
650 "# ifdef VERTEX_SHADER\n"
653 " gl_FrontColor = gl_Color;\n"
654 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
655 " gl_Position = ftransform();\n"
658 "# ifdef FRAGMENT_SHADER\n"
660 "uniform sampler2D Texture_First;\n"
661 "uniform vec4 BloomBlur_Parameters;\n"
666 " vec2 tc = gl_TexCoord[0].xy;\n"
667 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
668 " tc += BloomBlur_Parameters.xy;\n"
669 " for (i = 1;i < SAMPLES;i++)\n"
671 " color += texture2D(Texture_First, tc).rgb;\n"
672 " tc += BloomBlur_Parameters.xy;\n"
674 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
678 "#else // !MODE_BLOOMBLUR\n"
680 "varying vec2 TexCoord;\n"
681 "#ifdef USEVERTEXTEXTUREBLEND\n"
682 "varying vec2 TexCoord2;\n"
684 "varying vec2 TexCoordLightmap;\n"
686 "#ifdef MODE_LIGHTSOURCE\n"
687 "varying vec3 CubeVector;\n"
690 "#ifdef MODE_LIGHTSOURCE\n"
691 "varying vec3 LightVector;\n"
693 "#ifdef MODE_LIGHTDIRECTION\n"
694 "varying vec3 LightVector;\n"
697 "varying vec3 EyeVector;\n"
699 "varying vec3 EyeVectorModelSpace;\n"
700 "varying float FogPlaneVertexDist;\n"
703 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
704 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
705 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
707 "#ifdef MODE_WATER\n"
708 "varying vec4 ModelViewProjectionPosition;\n"
710 "#ifdef MODE_REFRACTION\n"
711 "varying vec4 ModelViewProjectionPosition;\n"
713 "#ifdef USEREFLECTION\n"
714 "varying vec4 ModelViewProjectionPosition;\n"
721 "// vertex shader specific:\n"
722 "#ifdef VERTEX_SHADER\n"
724 "uniform vec3 LightPosition;\n"
725 "uniform vec3 EyePosition;\n"
726 "uniform vec3 LightDir;\n"
727 "uniform vec4 FogPlane;\n"
729 "// 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"
733 " gl_FrontColor = gl_Color;\n"
734 " // copy the surface texcoord\n"
735 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
736 "#ifdef USEVERTEXTEXTUREBLEND\n"
737 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
739 "#ifndef MODE_LIGHTSOURCE\n"
740 "# ifndef MODE_LIGHTDIRECTION\n"
741 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
745 "#ifdef MODE_LIGHTSOURCE\n"
746 " // transform vertex position into light attenuation/cubemap space\n"
747 " // (-1 to +1 across the light box)\n"
748 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
750 " // transform unnormalized light direction into tangent space\n"
751 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
752 " // normalize it per pixel)\n"
753 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
754 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
755 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
756 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
759 "#ifdef MODE_LIGHTDIRECTION\n"
760 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
761 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
762 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
765 " // transform unnormalized eye direction into tangent space\n"
767 " vec3 EyeVectorModelSpace;\n"
769 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
770 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
771 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
772 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
775 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
778 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
779 " VectorS = gl_MultiTexCoord1.xyz;\n"
780 " VectorT = gl_MultiTexCoord2.xyz;\n"
781 " VectorR = gl_MultiTexCoord3.xyz;\n"
784 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
785 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
786 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
787 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
790 "// transform vertex to camera space, using ftransform to match non-VS\n"
792 " gl_Position = ftransform();\n"
794 "#ifdef MODE_WATER\n"
795 " ModelViewProjectionPosition = gl_Position;\n"
797 "#ifdef MODE_REFRACTION\n"
798 " ModelViewProjectionPosition = gl_Position;\n"
800 "#ifdef USEREFLECTION\n"
801 " ModelViewProjectionPosition = gl_Position;\n"
805 "#endif // VERTEX_SHADER\n"
810 "// fragment shader specific:\n"
811 "#ifdef FRAGMENT_SHADER\n"
813 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
814 "uniform sampler2D Texture_Normal;\n"
815 "uniform sampler2D Texture_Color;\n"
816 "uniform sampler2D Texture_Gloss;\n"
817 "uniform sampler2D Texture_Glow;\n"
818 "uniform sampler2D Texture_SecondaryNormal;\n"
819 "uniform sampler2D Texture_SecondaryColor;\n"
820 "uniform sampler2D Texture_SecondaryGloss;\n"
821 "uniform sampler2D Texture_SecondaryGlow;\n"
822 "uniform sampler2D Texture_Pants;\n"
823 "uniform sampler2D Texture_Shirt;\n"
824 "uniform sampler2D Texture_FogMask;\n"
825 "uniform sampler2D Texture_Lightmap;\n"
826 "uniform sampler2D Texture_Deluxemap;\n"
827 "uniform sampler2D Texture_Refraction;\n"
828 "uniform sampler2D Texture_Reflection;\n"
829 "uniform sampler2D Texture_Attenuation;\n"
830 "uniform samplerCube Texture_Cube;\n"
832 "#define showshadowmap 0\n"
834 "#ifdef USESHADOWMAPRECT\n"
835 "# ifdef USESHADOWSAMPLER\n"
836 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
838 "uniform sampler2DRect Texture_ShadowMapRect;\n"
842 "#ifdef USESHADOWMAP2D\n"
843 "# ifdef USESHADOWSAMPLER\n"
844 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
846 "uniform sampler2D Texture_ShadowMap2D;\n"
850 "#ifdef USESHADOWMAPVSDCT\n"
851 "uniform samplerCube Texture_CubeProjection;\n"
854 "#ifdef USESHADOWMAPCUBE\n"
855 "# ifdef USESHADOWSAMPLER\n"
856 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
858 "uniform samplerCube Texture_ShadowMapCube;\n"
862 "uniform myhalf3 LightColor;\n"
863 "uniform myhalf3 AmbientColor;\n"
864 "uniform myhalf3 DiffuseColor;\n"
865 "uniform myhalf3 SpecularColor;\n"
866 "uniform myhalf3 Color_Pants;\n"
867 "uniform myhalf3 Color_Shirt;\n"
868 "uniform myhalf3 FogColor;\n"
870 "uniform myhalf4 TintColor;\n"
873 "//#ifdef MODE_WATER\n"
874 "uniform vec4 DistortScaleRefractReflect;\n"
875 "uniform vec4 ScreenScaleRefractReflect;\n"
876 "uniform vec4 ScreenCenterRefractReflect;\n"
877 "uniform myhalf4 RefractColor;\n"
878 "uniform myhalf4 ReflectColor;\n"
879 "uniform myhalf ReflectFactor;\n"
880 "uniform myhalf ReflectOffset;\n"
882 "//# ifdef MODE_REFRACTION\n"
883 "//uniform vec4 DistortScaleRefractReflect;\n"
884 "//uniform vec4 ScreenScaleRefractReflect;\n"
885 "//uniform vec4 ScreenCenterRefractReflect;\n"
886 "//uniform myhalf4 RefractColor;\n"
887 "//# ifdef USEREFLECTION\n"
888 "//uniform myhalf4 ReflectColor;\n"
891 "//# ifdef USEREFLECTION\n"
892 "//uniform vec4 DistortScaleRefractReflect;\n"
893 "//uniform vec4 ScreenScaleRefractReflect;\n"
894 "//uniform vec4 ScreenCenterRefractReflect;\n"
895 "//uniform myhalf4 ReflectColor;\n"
900 "uniform myhalf3 GlowColor;\n"
901 "uniform myhalf SceneBrightness;\n"
903 "uniform float OffsetMapping_Scale;\n"
904 "uniform float OffsetMapping_Bias;\n"
905 "uniform float FogRangeRecip;\n"
906 "uniform float FogPlaneViewDist;\n"
907 "uniform float FogHeightFade;\n"
909 "uniform myhalf AmbientScale;\n"
910 "uniform myhalf DiffuseScale;\n"
911 "uniform myhalf SpecularScale;\n"
912 "uniform myhalf SpecularPower;\n"
914 "#ifdef USEOFFSETMAPPING\n"
915 "vec2 OffsetMapping(vec2 TexCoord)\n"
917 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
918 " // 14 sample relief mapping: linear search and then binary search\n"
919 " // this basically steps forward a small amount repeatedly until it finds\n"
920 " // itself inside solid, then jitters forward and back using decreasing\n"
921 " // amounts to find the impact\n"
922 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
923 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
924 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
925 " vec3 RT = vec3(TexCoord, 1);\n"
926 " OffsetVector *= 0.1;\n"
927 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
928 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
929 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
930 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
931 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
932 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
933 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
934 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
935 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
936 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
937 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
938 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
939 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
940 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
943 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
944 " // this basically moves forward the full distance, and then backs up based\n"
945 " // on height of samples\n"
946 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
947 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
948 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
949 " TexCoord += OffsetVector;\n"
950 " OffsetVector *= 0.333;\n"
951 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
952 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
953 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
954 " return TexCoord;\n"
957 "#endif // USEOFFSETMAPPING\n"
959 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
960 "uniform vec2 ShadowMap_TextureScale;\n"
961 "uniform vec4 ShadowMap_Parameters;\n"
964 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
965 "vec3 GetShadowMapTC2D(vec3 dir)\n"
967 " vec3 adir = abs(dir);\n"
968 "# ifndef USESHADOWMAPVSDCT\n"
972 " if (adir.x > adir.y)\n"
974 " if (adir.x > adir.z) // X\n"
978 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
984 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
989 " if (adir.y > adir.z) // Y\n"
993 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
999 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1003 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1004 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1005 " stc.z += ShadowMap_Parameters.z;\n"
1006 "# if showshadowmap\n"
1007 " stc.xy *= ShadowMap_TextureScale;\n"
1011 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1012 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1013 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1014 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1015 " stc.z += ShadowMap_Parameters.z;\n"
1016 "# if showshadowmap\n"
1017 " stc.xy *= ShadowMap_TextureScale;\n"
1022 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1024 "#ifdef USESHADOWMAPCUBE\n"
1025 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1027 " vec3 adir = abs(dir);\n"
1028 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1032 "#if !showshadowmap\n"
1033 "# ifdef USESHADOWMAPRECT\n"
1034 "float ShadowMapCompare(vec3 dir)\n"
1036 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1038 "# ifdef USESHADOWSAMPLER\n"
1040 "# ifdef USESHADOWMAPPCF\n"
1041 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1042 " 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"
1044 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1049 "# ifdef USESHADOWMAPPCF\n"
1050 "# if USESHADOWMAPPCF > 1\n"
1051 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1052 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1053 " 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"
1054 " 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"
1055 " 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"
1056 " 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"
1057 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1058 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1060 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1061 " vec2 offset = fract(shadowmaptc.xy);\n"
1062 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1063 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1064 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1065 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1066 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1069 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1077 "# ifdef USESHADOWMAP2D\n"
1078 "float ShadowMapCompare(vec3 dir)\n"
1080 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1083 "# ifdef USESHADOWSAMPLER\n"
1084 "# ifdef USESHADOWMAPPCF\n"
1085 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1086 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1087 " 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"
1089 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1092 "# ifdef USESHADOWMAPPCF\n"
1093 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1094 "# ifdef GL_ARB_texture_gather\n"
1095 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1097 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1099 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1100 " center *= ShadowMap_TextureScale;\n"
1101 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1102 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1103 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1104 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1105 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1106 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1107 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1109 "# ifdef GL_EXT_gpu_shader4\n"
1110 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1112 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1114 "# if USESHADOWMAPPCF > 1\n"
1115 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1116 " center *= ShadowMap_TextureScale;\n"
1117 " 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"
1118 " 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"
1119 " 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"
1120 " 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"
1121 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1122 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1124 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1125 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1126 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1127 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1128 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1129 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1133 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1140 "# ifdef USESHADOWMAPCUBE\n"
1141 "float ShadowMapCompare(vec3 dir)\n"
1143 " // apply depth texture cubemap as light filter\n"
1144 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1146 "# ifdef USESHADOWSAMPLER\n"
1147 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1149 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1156 "#ifdef MODE_WATER\n"
1161 "#ifdef USEOFFSETMAPPING\n"
1162 " // apply offsetmapping\n"
1163 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1164 "#define TexCoord TexCoordOffset\n"
1167 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1168 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1169 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1170 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1171 " // FIXME temporary hack to detect the case that the reflection\n"
1172 " // gets blackened at edges due to leaving the area that contains actual\n"
1174 " // Remove this 'ack once we have a better way to stop this thing from\n"
1176 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1177 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1178 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1179 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1180 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1181 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1182 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1183 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1184 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1185 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1186 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1187 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1190 "#else // !MODE_WATER\n"
1191 "#ifdef MODE_REFRACTION\n"
1193 "// refraction pass\n"
1196 "#ifdef USEOFFSETMAPPING\n"
1197 " // apply offsetmapping\n"
1198 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1199 "#define TexCoord TexCoordOffset\n"
1202 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1203 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1204 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1205 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1206 " // FIXME temporary hack to detect the case that the reflection\n"
1207 " // gets blackened at edges due to leaving the area that contains actual\n"
1209 " // Remove this 'ack once we have a better way to stop this thing from\n"
1211 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1212 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1213 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1214 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1215 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1216 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1219 "#else // !MODE_REFRACTION\n"
1222 "#ifdef USEOFFSETMAPPING\n"
1223 " // apply offsetmapping\n"
1224 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1225 "#define TexCoord TexCoordOffset\n"
1228 " // combine the diffuse textures (base, pants, shirt)\n"
1229 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1230 "#ifdef USECOLORMAPPING\n"
1231 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1233 "#ifdef USEVERTEXTEXTUREBLEND\n"
1234 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1235 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1236 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1237 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1239 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1242 "#ifdef USEDIFFUSE\n"
1243 " // get the surface normal and the gloss color\n"
1244 "# ifdef USEVERTEXTEXTUREBLEND\n"
1245 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1246 "# ifdef USESPECULAR\n"
1247 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1250 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1251 "# ifdef USESPECULAR\n"
1252 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1259 "#ifdef MODE_LIGHTSOURCE\n"
1260 " // light source\n"
1262 " // calculate surface normal, light normal, and specular normal\n"
1263 " // compute color intensity for the two textures (colormap and glossmap)\n"
1264 " // scale by light color and attenuation as efficiently as possible\n"
1265 " // (do as much scalar math as possible rather than vector math)\n"
1266 "# ifdef USEDIFFUSE\n"
1267 " // get the light normal\n"
1268 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1270 "# ifdef USESPECULAR\n"
1271 "# ifndef USEEXACTSPECULARMATH\n"
1272 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1275 " // calculate directional shading\n"
1276 "# ifdef USEEXACTSPECULARMATH\n"
1277 " 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"
1279 " 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"
1282 "# ifdef USEDIFFUSE\n"
1283 " // calculate directional shading\n"
1284 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1286 " // calculate directionless shading\n"
1287 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1291 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1292 "#if !showshadowmap\n"
1293 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1297 "# ifdef USECUBEFILTER\n"
1298 " // apply light cubemap filter\n"
1299 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1300 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1302 "#endif // MODE_LIGHTSOURCE\n"
1307 "#ifdef MODE_LIGHTDIRECTION\n"
1308 " // directional model lighting\n"
1309 "# ifdef USEDIFFUSE\n"
1310 " // get the light normal\n"
1311 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1313 "# ifdef USESPECULAR\n"
1314 " // calculate directional shading\n"
1315 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1316 "# ifdef USEEXACTSPECULARMATH\n"
1317 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1319 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1320 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1323 "# ifdef USEDIFFUSE\n"
1325 " // calculate directional shading\n"
1326 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1328 " color.rgb *= AmbientColor;\n"
1331 "#endif // MODE_LIGHTDIRECTION\n"
1336 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1337 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1339 " // get the light normal\n"
1340 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1341 " myhalf3 diffusenormal;\n"
1342 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1343 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1344 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1345 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1346 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1347 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1348 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1349 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1350 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1351 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1352 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1353 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1354 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1355 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1356 "# ifdef USESPECULAR\n"
1357 "# ifdef USEEXACTSPECULARMATH\n"
1358 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1360 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1361 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1365 " // apply lightmap color\n"
1366 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1367 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1372 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1373 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1375 " // get the light normal\n"
1376 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1377 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1378 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1379 "# ifdef USESPECULAR\n"
1380 "# ifdef USEEXACTSPECULARMATH\n"
1381 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1383 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1384 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1388 " // apply lightmap color\n"
1389 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1390 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1395 "#ifdef MODE_LIGHTMAP\n"
1396 " // apply lightmap color\n"
1397 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1398 "#endif // MODE_LIGHTMAP\n"
1403 "#ifdef MODE_VERTEXCOLOR\n"
1404 " // apply lightmap color\n"
1405 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1406 "#endif // MODE_VERTEXCOLOR\n"
1411 "#ifdef MODE_FLATCOLOR\n"
1412 "#endif // MODE_FLATCOLOR\n"
1420 " color *= TintColor;\n"
1423 "#ifdef USEVERTEXTEXTUREBLEND\n"
1424 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1426 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1430 " color.rgb *= SceneBrightness;\n"
1432 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1435 "#ifdef USEFOGOUTSIDE\n"
1436 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1438 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1440 "// float FogHeightFade1 = -0.5/1024.0;\n"
1441 "// if (FogPlaneViewDist >= 0.0)\n"
1442 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade1);\n"
1444 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade1);\n"
1445 "//# ifdef USEFOGABOVE\n"
1446 "// if (FogPlaneViewDist >= 0.0)\n"
1447 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist);\n"
1449 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist));\n"
1450 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1451 "// fogfrac *= min(1.0, (max(0.0, fade*FogPlaneVertexDist) + max(0.0, fade*FogPlaneViewDist)));\n"
1452 "// fogfrac *= min(1.0, (max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1453 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1455 " //fogfrac *= min(1.0, max(0.0, (max(-2048, min(0, FogPlaneVertexDist)) + max(-2048, min(0, FogPlaneViewDist)))/-2048.0));\n"
1456 " //float fade = -0.5/128.0;\n"
1457 " //fogfrac *= max(0.0, min(1.0, fade*FogPlaneVertexDist)) + max(0.0, min(1.0, fade*FogPlaneViewDist));\n"
1458 " //fogfrac *= max(0.0, min(1.0, FogHeightFade1*FogPlaneVertexDist)) + max(0.0, min(1.0, FogHeightFade1*FogPlaneViewDist));\n"
1459 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1460 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1461 " //fogfrac *= min(1.0, min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1462 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1463 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1464 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1466 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0))));\n"
1469 " // 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"
1470 "#ifdef USEREFLECTION\n"
1471 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1472 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1473 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1474 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1475 " // FIXME temporary hack to detect the case that the reflection\n"
1476 " // gets blackened at edges due to leaving the area that contains actual\n"
1478 " // Remove this 'ack once we have a better way to stop this thing from\n"
1480 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1481 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1482 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1483 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1484 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1485 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1488 " gl_FragColor = vec4(color);\n"
1490 "#if showshadowmap\n"
1491 "# ifdef USESHADOWMAPRECT\n"
1492 "# ifdef USESHADOWSAMPLER\n"
1493 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1495 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1498 "# ifdef USESHADOWMAP2D\n"
1499 "# ifdef USESHADOWSAMPLER\n"
1500 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1502 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1506 "# ifdef USESHADOWMAPCUBE\n"
1507 "# ifdef USESHADOWSAMPLER\n"
1508 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1510 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1515 "#endif // !MODE_REFRACTION\n"
1516 "#endif // !MODE_WATER\n"
1518 "#endif // FRAGMENT_SHADER\n"
1520 "#endif // !MODE_BLOOMBLUR\n"
1521 "#endif // !MODE_GENERIC\n"
1522 "#endif // !MODE_POSTPROCESS\n"
1523 "#endif // !MODE_SHOWDEPTH\n"
1524 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1527 typedef struct shaderpermutationinfo_s
1529 const char *pretext;
1532 shaderpermutationinfo_t;
1534 typedef struct shadermodeinfo_s
1536 const char *vertexfilename;
1537 const char *geometryfilename;
1538 const char *fragmentfilename;
1539 const char *pretext;
1544 typedef enum shaderpermutation_e
1546 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1547 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1548 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1549 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1550 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1551 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1552 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1553 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1554 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1555 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1556 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1557 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1558 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1559 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1560 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1561 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1562 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1563 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1564 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1565 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1566 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1567 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1568 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1569 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1570 SHADERPERMUTATION_LIMIT = 1<<24, ///< size of permutations array
1571 SHADERPERMUTATION_COUNT = 24 ///< size of shaderpermutationinfo array
1573 shaderpermutation_t;
1575 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1576 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1578 {"#define USEDIFFUSE\n", " diffuse"},
1579 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1580 {"#define USEVIEWTINT\n", " viewtint"},
1581 {"#define USECOLORMAPPING\n", " colormapping"},
1582 {"#define USESATURATION\n", " saturation"},
1583 {"#define USEFOGINSIDE\n", " foginside"},
1584 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1585 {"#define USEGAMMARAMPS\n", " gammaramps"},
1586 {"#define USECUBEFILTER\n", " cubefilter"},
1587 {"#define USEGLOW\n", " glow"},
1588 {"#define USEBLOOM\n", " bloom"},
1589 {"#define USESPECULAR\n", " specular"},
1590 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1591 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1592 {"#define USEREFLECTION\n", " reflection"},
1593 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1594 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1595 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1596 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1597 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1598 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1599 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1600 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1601 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1604 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1605 typedef enum shadermode_e
1607 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1608 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1609 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1610 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1611 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1612 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1613 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1614 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1615 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1616 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1617 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1618 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1619 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1624 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1625 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1627 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1628 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1629 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1630 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1631 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1632 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1633 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1634 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1635 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1636 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1637 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1638 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1639 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1642 struct r_glsl_permutation_s;
1643 typedef struct r_glsl_permutation_s
1645 /// hash lookup data
1646 struct r_glsl_permutation_s *hashnext;
1648 unsigned int permutation;
1650 /// indicates if we have tried compiling this permutation already
1652 /// 0 if compilation failed
1654 /// locations of detected uniforms in program object, or -1 if not found
1655 int loc_Texture_First;
1656 int loc_Texture_Second;
1657 int loc_Texture_GammaRamps;
1658 int loc_Texture_Normal;
1659 int loc_Texture_Color;
1660 int loc_Texture_Gloss;
1661 int loc_Texture_Glow;
1662 int loc_Texture_SecondaryNormal;
1663 int loc_Texture_SecondaryColor;
1664 int loc_Texture_SecondaryGloss;
1665 int loc_Texture_SecondaryGlow;
1666 int loc_Texture_Pants;
1667 int loc_Texture_Shirt;
1668 int loc_Texture_FogMask;
1669 int loc_Texture_Lightmap;
1670 int loc_Texture_Deluxemap;
1671 int loc_Texture_Attenuation;
1672 int loc_Texture_Cube;
1673 int loc_Texture_Refraction;
1674 int loc_Texture_Reflection;
1675 int loc_Texture_ShadowMapRect;
1676 int loc_Texture_ShadowMapCube;
1677 int loc_Texture_ShadowMap2D;
1678 int loc_Texture_CubeProjection;
1680 int loc_LightPosition;
1681 int loc_EyePosition;
1682 int loc_Color_Pants;
1683 int loc_Color_Shirt;
1685 int loc_FogPlaneViewDist;
1686 int loc_FogRangeRecip;
1687 int loc_FogHeightFade;
1688 int loc_AmbientScale;
1689 int loc_DiffuseScale;
1690 int loc_SpecularScale;
1691 int loc_SpecularPower;
1693 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1694 int loc_OffsetMapping_Scale;
1696 int loc_AmbientColor;
1697 int loc_DiffuseColor;
1698 int loc_SpecularColor;
1700 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1701 int loc_GammaCoeff; ///< 1 / gamma
1702 int loc_DistortScaleRefractReflect;
1703 int loc_ScreenScaleRefractReflect;
1704 int loc_ScreenCenterRefractReflect;
1705 int loc_RefractColor;
1706 int loc_ReflectColor;
1707 int loc_ReflectFactor;
1708 int loc_ReflectOffset;
1716 int loc_ShadowMap_TextureScale;
1717 int loc_ShadowMap_Parameters;
1719 r_glsl_permutation_t;
1721 #define SHADERPERMUTATION_HASHSIZE 256
1723 /// information about each possible shader permutation
1724 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1725 /// currently selected permutation
1726 r_glsl_permutation_t *r_glsl_permutation;
1727 /// storage for permutations linked in the hash table
1728 memexpandablearray_t r_glsl_permutationarray;
1730 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1732 //unsigned int hashdepth = 0;
1733 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1734 r_glsl_permutation_t *p;
1735 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1737 if (p->mode == mode && p->permutation == permutation)
1739 //if (hashdepth > 10)
1740 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1745 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1747 p->permutation = permutation;
1748 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1749 r_glsl_permutationhash[mode][hashindex] = p;
1750 //if (hashdepth > 10)
1751 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1755 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1758 if (!filename || !filename[0])
1760 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1763 if (printfromdisknotice)
1764 Con_DPrint("from disk... ");
1765 return shaderstring;
1767 else if (!strcmp(filename, "glsl/default.glsl"))
1769 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1770 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1772 return shaderstring;
1775 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1778 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1779 int vertstrings_count = 0;
1780 int geomstrings_count = 0;
1781 int fragstrings_count = 0;
1782 char *vertexstring, *geometrystring, *fragmentstring;
1783 const char *vertstrings_list[32+3];
1784 const char *geomstrings_list[32+3];
1785 const char *fragstrings_list[32+3];
1786 char permutationname[256];
1793 permutationname[0] = 0;
1794 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1795 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1796 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1798 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1800 // the first pretext is which type of shader to compile as
1801 // (later these will all be bound together as a program object)
1802 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1803 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1804 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1806 // the second pretext is the mode (for example a light source)
1807 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1808 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1809 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1810 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1812 // now add all the permutation pretexts
1813 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1815 if (permutation & (1<<i))
1817 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1818 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1819 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1820 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1824 // keep line numbers correct
1825 vertstrings_list[vertstrings_count++] = "\n";
1826 geomstrings_list[geomstrings_count++] = "\n";
1827 fragstrings_list[fragstrings_count++] = "\n";
1831 // now append the shader text itself
1832 vertstrings_list[vertstrings_count++] = vertexstring;
1833 geomstrings_list[geomstrings_count++] = geometrystring;
1834 fragstrings_list[fragstrings_count++] = fragmentstring;
1836 // if any sources were NULL, clear the respective list
1838 vertstrings_count = 0;
1839 if (!geometrystring)
1840 geomstrings_count = 0;
1841 if (!fragmentstring)
1842 fragstrings_count = 0;
1844 // compile the shader program
1845 if (vertstrings_count + geomstrings_count + fragstrings_count)
1846 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1850 qglUseProgramObjectARB(p->program);CHECKGLERROR
1851 // look up all the uniform variable names we care about, so we don't
1852 // have to look them up every time we set them
1853 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1854 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1855 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1856 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1857 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1858 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1859 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1860 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1861 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1862 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1863 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1864 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1865 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1866 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1867 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1868 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1869 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1870 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1871 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1872 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1873 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1874 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1875 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1876 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1877 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1878 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1879 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1880 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1881 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1882 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
1883 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
1884 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1885 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
1886 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1887 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1888 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1889 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1890 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1891 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1892 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1893 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1894 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1895 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1896 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1897 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1898 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1899 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1900 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1901 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1902 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1903 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1904 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1905 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1906 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1907 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1908 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1909 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1910 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1911 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1912 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1913 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1914 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1915 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1916 // initialize the samplers to refer to the texture units we use
1917 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1918 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1919 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1920 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1921 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1922 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1923 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1924 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1925 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1926 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1927 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1928 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1929 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1930 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1931 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1932 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1933 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1934 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1935 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1936 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1937 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1938 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1939 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1940 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1942 if (developer.integer)
1943 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1946 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1950 Mem_Free(vertexstring);
1952 Mem_Free(geometrystring);
1954 Mem_Free(fragmentstring);
1957 void R_GLSL_Restart_f(void)
1959 unsigned int i, limit;
1960 r_glsl_permutation_t *p;
1961 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1962 for (i = 0;i < limit;i++)
1964 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1966 GL_Backend_FreeProgram(p->program);
1967 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1970 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1973 void R_GLSL_DumpShader_f(void)
1977 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1980 Con_Printf("failed to write to glsl/default.glsl\n");
1984 FS_Print(file, "/* The engine may define the following macros:\n");
1985 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1986 for (i = 0;i < SHADERMODE_COUNT;i++)
1987 FS_Print(file, shadermodeinfo[i].pretext);
1988 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1989 FS_Print(file, shaderpermutationinfo[i].pretext);
1990 FS_Print(file, "*/\n");
1991 FS_Print(file, builtinshaderstring);
1994 Con_Printf("glsl/default.glsl written\n");
1997 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1999 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2000 if (r_glsl_permutation != perm)
2002 r_glsl_permutation = perm;
2003 if (!r_glsl_permutation->program)
2005 if (!r_glsl_permutation->compiled)
2006 R_GLSL_CompilePermutation(perm, mode, permutation);
2007 if (!r_glsl_permutation->program)
2009 // remove features until we find a valid permutation
2011 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2013 // reduce i more quickly whenever it would not remove any bits
2014 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2015 if (!(permutation & j))
2018 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2019 if (!r_glsl_permutation->compiled)
2020 R_GLSL_CompilePermutation(perm, mode, permutation);
2021 if (r_glsl_permutation->program)
2024 if (i >= SHADERPERMUTATION_COUNT)
2026 Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
2027 Cvar_SetValueQuick(&r_glsl, 0);
2028 R_GLSL_Restart_f(); // unload shaders
2029 return; // no bit left to clear
2034 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2038 void R_SetupGenericShader(qboolean usetexture)
2040 if (gl_support_fragment_shader)
2042 if (r_glsl.integer && r_glsl_usegeneric.integer)
2043 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2044 else if (r_glsl_permutation)
2046 r_glsl_permutation = NULL;
2047 qglUseProgramObjectARB(0);CHECKGLERROR
2052 void R_SetupGenericTwoTextureShader(int texturemode)
2054 if (gl_support_fragment_shader)
2056 if (r_glsl.integer && r_glsl_usegeneric.integer)
2057 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))));
2058 else if (r_glsl_permutation)
2060 r_glsl_permutation = NULL;
2061 qglUseProgramObjectARB(0);CHECKGLERROR
2064 if (!r_glsl_permutation)
2066 if (texturemode == GL_DECAL && gl_combine.integer)
2067 texturemode = GL_INTERPOLATE_ARB;
2068 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
2072 void R_SetupDepthOrShadowShader(void)
2074 if (gl_support_fragment_shader)
2076 if (r_glsl.integer && r_glsl_usegeneric.integer)
2077 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2078 else if (r_glsl_permutation)
2080 r_glsl_permutation = NULL;
2081 qglUseProgramObjectARB(0);CHECKGLERROR
2086 void R_SetupShowDepthShader(void)
2088 if (gl_support_fragment_shader)
2090 if (r_glsl.integer && r_glsl_usegeneric.integer)
2091 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2092 else if (r_glsl_permutation)
2094 r_glsl_permutation = NULL;
2095 qglUseProgramObjectARB(0);CHECKGLERROR
2100 extern rtexture_t *r_shadow_attenuationgradienttexture;
2101 extern rtexture_t *r_shadow_attenuation2dtexture;
2102 extern rtexture_t *r_shadow_attenuation3dtexture;
2103 extern qboolean r_shadow_usingshadowmaprect;
2104 extern qboolean r_shadow_usingshadowmapcube;
2105 extern qboolean r_shadow_usingshadowmap2d;
2106 extern float r_shadow_shadowmap_texturescale[2];
2107 extern float r_shadow_shadowmap_parameters[4];
2108 extern qboolean r_shadow_shadowmapvsdct;
2109 extern qboolean r_shadow_shadowmapsampler;
2110 extern int r_shadow_shadowmappcf;
2111 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2113 // select a permutation of the lighting shader appropriate to this
2114 // combination of texture, entity, light source, and fogging, only use the
2115 // minimum features necessary to avoid wasting rendering time in the
2116 // fragment shader on features that are not being used
2117 unsigned int permutation = 0;
2118 unsigned int mode = 0;
2119 // TODO: implement geometry-shader based shadow volumes someday
2120 if (r_glsl_offsetmapping.integer)
2122 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2123 if (r_glsl_offsetmapping_reliefmapping.integer)
2124 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2126 if (rsurfacepass == RSURFPASS_BACKGROUND)
2128 // distorted background
2129 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2130 mode = SHADERMODE_WATER;
2132 mode = SHADERMODE_REFRACTION;
2134 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2137 mode = SHADERMODE_LIGHTSOURCE;
2138 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2139 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2140 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2141 permutation |= SHADERPERMUTATION_CUBEFILTER;
2142 if (diffusescale > 0)
2143 permutation |= SHADERPERMUTATION_DIFFUSE;
2144 if (specularscale > 0)
2145 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2146 if (r_refdef.fogenabled)
2147 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2148 if (rsurface.texture->colormapping)
2149 permutation |= SHADERPERMUTATION_COLORMAPPING;
2150 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2152 if (r_shadow_usingshadowmaprect)
2153 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2154 if (r_shadow_usingshadowmap2d)
2155 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2156 if (r_shadow_usingshadowmapcube)
2157 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2158 else if(r_shadow_shadowmapvsdct)
2159 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2161 if (r_shadow_shadowmapsampler)
2162 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2163 if (r_shadow_shadowmappcf > 1)
2164 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2165 else if (r_shadow_shadowmappcf)
2166 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2169 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2171 // unshaded geometry (fullbright or ambient model lighting)
2172 mode = SHADERMODE_FLATCOLOR;
2173 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2174 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2175 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2176 permutation |= SHADERPERMUTATION_GLOW;
2177 if (r_refdef.fogenabled)
2178 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2179 if (rsurface.texture->colormapping)
2180 permutation |= SHADERPERMUTATION_COLORMAPPING;
2181 if (r_glsl_offsetmapping.integer)
2183 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2184 if (r_glsl_offsetmapping_reliefmapping.integer)
2185 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2187 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2188 permutation |= SHADERPERMUTATION_REFLECTION;
2190 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2192 // directional model lighting
2193 mode = SHADERMODE_LIGHTDIRECTION;
2194 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2195 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2196 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2197 permutation |= SHADERPERMUTATION_GLOW;
2198 permutation |= SHADERPERMUTATION_DIFFUSE;
2199 if (specularscale > 0)
2200 permutation |= SHADERPERMUTATION_SPECULAR;
2201 if (r_refdef.fogenabled)
2202 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2203 if (rsurface.texture->colormapping)
2204 permutation |= SHADERPERMUTATION_COLORMAPPING;
2205 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2206 permutation |= SHADERPERMUTATION_REFLECTION;
2208 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2210 // ambient model lighting
2211 mode = SHADERMODE_LIGHTDIRECTION;
2212 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2213 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2214 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2215 permutation |= SHADERPERMUTATION_GLOW;
2216 if (r_refdef.fogenabled)
2217 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2218 if (rsurface.texture->colormapping)
2219 permutation |= SHADERPERMUTATION_COLORMAPPING;
2220 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2221 permutation |= SHADERPERMUTATION_REFLECTION;
2226 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2228 // deluxemapping (light direction texture)
2229 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2230 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2232 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2233 permutation |= SHADERPERMUTATION_DIFFUSE;
2234 if (specularscale > 0)
2235 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2237 else if (r_glsl_deluxemapping.integer >= 2)
2239 // fake deluxemapping (uniform light direction in tangentspace)
2240 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2241 permutation |= SHADERPERMUTATION_DIFFUSE;
2242 if (specularscale > 0)
2243 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2245 else if (rsurface.uselightmaptexture)
2247 // ordinary lightmapping (q1bsp, q3bsp)
2248 mode = SHADERMODE_LIGHTMAP;
2252 // ordinary vertex coloring (q3bsp)
2253 mode = SHADERMODE_VERTEXCOLOR;
2255 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2256 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2257 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258 permutation |= SHADERPERMUTATION_GLOW;
2259 if (r_refdef.fogenabled)
2260 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2261 if (rsurface.texture->colormapping)
2262 permutation |= SHADERPERMUTATION_COLORMAPPING;
2263 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2264 permutation |= SHADERPERMUTATION_REFLECTION;
2266 if(permutation & SHADERPERMUTATION_SPECULAR)
2267 if(r_shadow_glossexact.integer)
2268 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2269 R_SetupShader_SetPermutation(mode, permutation);
2270 if (mode == SHADERMODE_LIGHTSOURCE)
2272 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2273 if (permutation & SHADERPERMUTATION_DIFFUSE)
2275 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2276 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2277 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2278 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2282 // ambient only is simpler
2283 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]);
2284 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2285 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2286 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2288 // additive passes are only darkened by fog, not tinted
2289 if (r_glsl_permutation->loc_FogColor >= 0)
2290 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2291 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]);
2292 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]);
2296 if (mode == SHADERMODE_LIGHTDIRECTION)
2298 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);
2299 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);
2300 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);
2301 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]);
2305 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2306 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2307 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2309 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]);
2310 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);
2311 // additive passes are only darkened by fog, not tinted
2312 if (r_glsl_permutation->loc_FogColor >= 0)
2314 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2315 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2317 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2319 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);
2320 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]);
2321 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]);
2322 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2323 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2324 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2325 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2327 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2328 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2329 if (r_glsl_permutation->loc_Color_Pants >= 0)
2331 if (rsurface.texture->currentskinframe->pants)
2332 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2334 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2336 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2338 if (rsurface.texture->currentskinframe->shirt)
2339 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2341 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2343 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]);
2344 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2345 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2346 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2347 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2349 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2353 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2355 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2359 #define SKINFRAME_HASH 1024
2363 int loadsequence; // incremented each level change
2364 memexpandablearray_t array;
2365 skinframe_t *hash[SKINFRAME_HASH];
2368 r_skinframe_t r_skinframe;
2370 void R_SkinFrame_PrepareForPurge(void)
2372 r_skinframe.loadsequence++;
2373 // wrap it without hitting zero
2374 if (r_skinframe.loadsequence >= 200)
2375 r_skinframe.loadsequence = 1;
2378 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2382 // mark the skinframe as used for the purging code
2383 skinframe->loadsequence = r_skinframe.loadsequence;
2386 void R_SkinFrame_Purge(void)
2390 for (i = 0;i < SKINFRAME_HASH;i++)
2392 for (s = r_skinframe.hash[i];s;s = s->next)
2394 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2396 if (s->merged == s->base)
2398 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2399 R_PurgeTexture(s->stain );s->stain = NULL;
2400 R_PurgeTexture(s->merged);s->merged = NULL;
2401 R_PurgeTexture(s->base );s->base = NULL;
2402 R_PurgeTexture(s->pants );s->pants = NULL;
2403 R_PurgeTexture(s->shirt );s->shirt = NULL;
2404 R_PurgeTexture(s->nmap );s->nmap = NULL;
2405 R_PurgeTexture(s->gloss );s->gloss = NULL;
2406 R_PurgeTexture(s->glow );s->glow = NULL;
2407 R_PurgeTexture(s->fog );s->fog = NULL;
2408 s->loadsequence = 0;
2414 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2416 char basename[MAX_QPATH];
2418 Image_StripImageExtension(name, basename, sizeof(basename));
2420 if( last == NULL ) {
2422 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2423 item = r_skinframe.hash[hashindex];
2428 // linearly search through the hash bucket
2429 for( ; item ; item = item->next ) {
2430 if( !strcmp( item->basename, basename ) ) {
2437 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2441 char basename[MAX_QPATH];
2443 Image_StripImageExtension(name, basename, sizeof(basename));
2445 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2446 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2447 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2451 rtexture_t *dyntexture;
2452 // check whether its a dynamic texture
2453 dyntexture = CL_GetDynTexture( basename );
2454 if (!add && !dyntexture)
2456 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2457 memset(item, 0, sizeof(*item));
2458 strlcpy(item->basename, basename, sizeof(item->basename));
2459 item->base = dyntexture; // either NULL or dyntexture handle
2460 item->textureflags = textureflags;
2461 item->comparewidth = comparewidth;
2462 item->compareheight = compareheight;
2463 item->comparecrc = comparecrc;
2464 item->next = r_skinframe.hash[hashindex];
2465 r_skinframe.hash[hashindex] = item;
2467 else if( item->base == NULL )
2469 rtexture_t *dyntexture;
2470 // check whether its a dynamic texture
2471 // 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]
2472 dyntexture = CL_GetDynTexture( basename );
2473 item->base = dyntexture; // either NULL or dyntexture handle
2476 R_SkinFrame_MarkUsed(item);
2480 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2482 unsigned long long avgcolor[5], wsum; \
2490 for(pix = 0; pix < cnt; ++pix) \
2493 for(comp = 0; comp < 3; ++comp) \
2495 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2498 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2500 for(comp = 0; comp < 3; ++comp) \
2501 avgcolor[comp] += getpixel * w; \
2504 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2505 avgcolor[4] += getpixel; \
2507 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2509 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2510 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2511 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2512 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2515 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2517 // FIXME: it should be possible to disable loading various layers using
2518 // cvars, to prevent wasted loading time and memory usage if the user does
2520 qboolean loadnormalmap = true;
2521 qboolean loadgloss = true;
2522 qboolean loadpantsandshirt = true;
2523 qboolean loadglow = true;
2525 unsigned char *pixels;
2526 unsigned char *bumppixels;
2527 unsigned char *basepixels = NULL;
2528 int basepixels_width;
2529 int basepixels_height;
2530 skinframe_t *skinframe;
2535 if (cls.state == ca_dedicated)
2538 // return an existing skinframe if already loaded
2539 // if loading of the first image fails, don't make a new skinframe as it
2540 // would cause all future lookups of this to be missing
2541 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2542 if (skinframe && skinframe->base)
2545 basepixels = loadimagepixelsbgra(name, complain, true);
2546 if (basepixels == NULL)
2549 if (developer_loading.integer)
2550 Con_Printf("loading skin \"%s\"\n", name);
2552 // we've got some pixels to store, so really allocate this new texture now
2554 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2555 skinframe->stain = NULL;
2556 skinframe->merged = NULL;
2557 skinframe->base = r_texture_notexture;
2558 skinframe->pants = NULL;
2559 skinframe->shirt = NULL;
2560 skinframe->nmap = r_texture_blanknormalmap;
2561 skinframe->gloss = NULL;
2562 skinframe->glow = NULL;
2563 skinframe->fog = NULL;
2565 basepixels_width = image_width;
2566 basepixels_height = image_height;
2567 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);
2569 if (textureflags & TEXF_ALPHA)
2571 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2572 if (basepixels[j] < 255)
2574 if (j < basepixels_width * basepixels_height * 4)
2576 // has transparent pixels
2579 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2580 for (j = 0;j < image_width * image_height * 4;j += 4)
2585 pixels[j+3] = basepixels[j+3];
2587 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);
2592 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2593 //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]);
2595 // _norm is the name used by tenebrae and has been adopted as standard
2598 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2600 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);
2604 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2606 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2607 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2608 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);
2610 Mem_Free(bumppixels);
2612 else if (r_shadow_bumpscale_basetexture.value > 0)
2614 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2615 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2616 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);
2620 // _luma is supported for tenebrae compatibility
2621 // (I think it's a very stupid name, but oh well)
2622 // _glow is the preferred name
2623 if (loadglow && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2624 if (loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2625 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2626 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2629 Mem_Free(basepixels);
2634 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2636 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, NULL);
2639 static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
2644 for (i = 0;i < width*height;i++)
2645 if (((unsigned char *)&palette[in[i]])[3] > 0)
2647 if (i == width*height)
2650 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2653 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2654 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2657 unsigned char *temp1, *temp2;
2658 skinframe_t *skinframe;
2660 if (cls.state == ca_dedicated)
2663 // if already loaded just return it, otherwise make a new skinframe
2664 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2665 if (skinframe && skinframe->base)
2668 skinframe->stain = NULL;
2669 skinframe->merged = NULL;
2670 skinframe->base = r_texture_notexture;
2671 skinframe->pants = NULL;
2672 skinframe->shirt = NULL;
2673 skinframe->nmap = r_texture_blanknormalmap;
2674 skinframe->gloss = NULL;
2675 skinframe->glow = NULL;
2676 skinframe->fog = NULL;
2678 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2682 if (developer_loading.integer)
2683 Con_Printf("loading 32bit skin \"%s\"\n", name);
2685 if (r_shadow_bumpscale_basetexture.value > 0)
2687 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2688 temp2 = temp1 + width * height * 4;
2689 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2690 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2693 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2694 if (textureflags & TEXF_ALPHA)
2696 for (i = 3;i < width * height * 4;i += 4)
2697 if (skindata[i] < 255)
2699 if (i < width * height * 4)
2701 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2702 memcpy(fogpixels, skindata, width * height * 4);
2703 for (i = 0;i < width * height * 4;i += 4)
2704 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2705 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2706 Mem_Free(fogpixels);
2710 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2711 //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]);
2716 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2719 unsigned char *temp1, *temp2;
2720 unsigned int *palette;
2721 skinframe_t *skinframe;
2723 if (cls.state == ca_dedicated)
2726 // if already loaded just return it, otherwise make a new skinframe
2727 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2728 if (skinframe && skinframe->base)
2731 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2733 skinframe->stain = NULL;
2734 skinframe->merged = NULL;
2735 skinframe->base = r_texture_notexture;
2736 skinframe->pants = NULL;
2737 skinframe->shirt = NULL;
2738 skinframe->nmap = r_texture_blanknormalmap;
2739 skinframe->gloss = NULL;
2740 skinframe->glow = NULL;
2741 skinframe->fog = NULL;
2743 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2747 if (developer_loading.integer)
2748 Con_Printf("loading quake skin \"%s\"\n", name);
2750 if (r_shadow_bumpscale_basetexture.value > 0)
2752 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2753 temp2 = temp1 + width * height * 4;
2754 // use either a custom palette or the quake palette
2755 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2756 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2757 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2760 // use either a custom palette, or the quake palette
2761 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2762 if (loadglowtexture)
2763 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2764 if (loadpantsandshirt)
2766 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2767 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2769 if (skinframe->pants || skinframe->shirt)
2770 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors
2771 if (textureflags & TEXF_ALPHA)
2773 for (i = 0;i < width * height;i++)
2774 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2776 if (i < width * height)
2777 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2780 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2781 //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]);
2786 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)
2789 skinframe_t *skinframe;
2791 if (cls.state == ca_dedicated)
2794 // if already loaded just return it, otherwise make a new skinframe
2795 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2796 if (skinframe && skinframe->base)
2799 skinframe->stain = NULL;
2800 skinframe->merged = NULL;
2801 skinframe->base = r_texture_notexture;
2802 skinframe->pants = NULL;
2803 skinframe->shirt = NULL;
2804 skinframe->nmap = r_texture_blanknormalmap;
2805 skinframe->gloss = NULL;
2806 skinframe->glow = NULL;
2807 skinframe->fog = NULL;
2809 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2813 if (developer_loading.integer)
2814 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2816 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, skinframe->basename, palette, skinframe->textureflags, true);
2817 if (textureflags & TEXF_ALPHA)
2819 for (i = 0;i < width * height;i++)
2820 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
2822 if (i < width * height)
2823 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
2826 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2827 //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]);
2832 skinframe_t *R_SkinFrame_LoadMissing(void)
2834 skinframe_t *skinframe;
2836 if (cls.state == ca_dedicated)
2839 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2840 skinframe->stain = NULL;
2841 skinframe->merged = NULL;
2842 skinframe->base = r_texture_notexture;
2843 skinframe->pants = NULL;
2844 skinframe->shirt = NULL;
2845 skinframe->nmap = r_texture_blanknormalmap;
2846 skinframe->gloss = NULL;
2847 skinframe->glow = NULL;
2848 skinframe->fog = NULL;
2850 skinframe->avgcolor[0] = rand() / RAND_MAX;
2851 skinframe->avgcolor[1] = rand() / RAND_MAX;
2852 skinframe->avgcolor[2] = rand() / RAND_MAX;
2853 skinframe->avgcolor[3] = 1;
2858 void R_Main_FreeViewCache(void)
2860 if (r_refdef.viewcache.entityvisible)
2861 Mem_Free(r_refdef.viewcache.entityvisible);
2862 if (r_refdef.viewcache.world_pvsbits)
2863 Mem_Free(r_refdef.viewcache.world_pvsbits);
2864 if (r_refdef.viewcache.world_leafvisible)
2865 Mem_Free(r_refdef.viewcache.world_leafvisible);
2866 if (r_refdef.viewcache.world_surfacevisible)
2867 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2868 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2871 void R_Main_ResizeViewCache(void)
2873 int numentities = r_refdef.scene.numentities;
2874 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
2875 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
2876 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
2877 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
2878 if (r_refdef.viewcache.maxentities < numentities)
2880 r_refdef.viewcache.maxentities = numentities;
2881 if (r_refdef.viewcache.entityvisible)
2882 Mem_Free(r_refdef.viewcache.entityvisible);
2883 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
2885 if (r_refdef.viewcache.world_numclusters != numclusters)
2887 r_refdef.viewcache.world_numclusters = numclusters;
2888 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
2889 if (r_refdef.viewcache.world_pvsbits)
2890 Mem_Free(r_refdef.viewcache.world_pvsbits);
2891 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
2893 if (r_refdef.viewcache.world_numleafs != numleafs)
2895 r_refdef.viewcache.world_numleafs = numleafs;
2896 if (r_refdef.viewcache.world_leafvisible)
2897 Mem_Free(r_refdef.viewcache.world_leafvisible);
2898 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
2900 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
2902 r_refdef.viewcache.world_numsurfaces = numsurfaces;
2903 if (r_refdef.viewcache.world_surfacevisible)
2904 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2905 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
2909 void gl_main_start(void)
2913 memset(r_queries, 0, sizeof(r_queries));
2915 r_qwskincache = NULL;
2916 r_qwskincache_size = 0;
2918 // set up r_skinframe loading system for textures
2919 memset(&r_skinframe, 0, sizeof(r_skinframe));
2920 r_skinframe.loadsequence = 1;
2921 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2923 r_main_texturepool = R_AllocTexturePool();
2924 R_BuildBlankTextures();
2926 if (gl_texturecubemap)
2929 R_BuildNormalizationCube();
2931 r_texture_fogattenuation = NULL;
2932 r_texture_gammaramps = NULL;
2933 //r_texture_fogintensity = NULL;
2934 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2935 memset(&r_waterstate, 0, sizeof(r_waterstate));
2936 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2937 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2938 memset(&r_svbsp, 0, sizeof (r_svbsp));
2940 r_refdef.fogmasktable_density = 0;
2943 extern rtexture_t *loadingscreentexture;
2944 void gl_main_shutdown(void)
2946 R_Main_FreeViewCache();
2949 qglDeleteQueriesARB(r_maxqueries, r_queries);
2953 memset(r_queries, 0, sizeof(r_queries));
2955 r_qwskincache = NULL;
2956 r_qwskincache_size = 0;
2958 // clear out the r_skinframe state
2959 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2960 memset(&r_skinframe, 0, sizeof(r_skinframe));
2963 Mem_Free(r_svbsp.nodes);
2964 memset(&r_svbsp, 0, sizeof (r_svbsp));
2965 R_FreeTexturePool(&r_main_texturepool);
2966 loadingscreentexture = NULL;
2967 r_texture_blanknormalmap = NULL;
2968 r_texture_white = NULL;
2969 r_texture_grey128 = NULL;
2970 r_texture_black = NULL;
2971 r_texture_whitecube = NULL;
2972 r_texture_normalizationcube = NULL;
2973 r_texture_fogattenuation = NULL;
2974 r_texture_gammaramps = NULL;
2975 //r_texture_fogintensity = NULL;
2976 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2977 memset(&r_waterstate, 0, sizeof(r_waterstate));
2981 extern void CL_ParseEntityLump(char *entitystring);
2982 void gl_main_newmap(void)
2984 // FIXME: move this code to client
2986 char *entities, entname[MAX_QPATH];
2988 Mem_Free(r_qwskincache);
2989 r_qwskincache = NULL;
2990 r_qwskincache_size = 0;
2993 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2994 l = (int)strlen(entname) - 4;
2995 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2997 memcpy(entname + l, ".ent", 5);
2998 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3000 CL_ParseEntityLump(entities);
3005 if (cl.worldmodel->brush.entities)
3006 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3008 R_Main_FreeViewCache();
3011 void GL_Main_Init(void)
3013 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3015 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3016 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3017 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3018 if (gamemode == GAME_NEHAHRA)
3020 Cvar_RegisterVariable (&gl_fogenable);
3021 Cvar_RegisterVariable (&gl_fogdensity);
3022 Cvar_RegisterVariable (&gl_fogred);
3023 Cvar_RegisterVariable (&gl_foggreen);
3024 Cvar_RegisterVariable (&gl_fogblue);
3025 Cvar_RegisterVariable (&gl_fogstart);
3026 Cvar_RegisterVariable (&gl_fogend);
3027 Cvar_RegisterVariable (&gl_skyclip);
3029 Cvar_RegisterVariable(&r_motionblur);
3030 Cvar_RegisterVariable(&r_motionblur_maxblur);
3031 Cvar_RegisterVariable(&r_motionblur_bmin);
3032 Cvar_RegisterVariable(&r_motionblur_vmin);
3033 Cvar_RegisterVariable(&r_motionblur_vmax);
3034 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3035 Cvar_RegisterVariable(&r_motionblur_randomize);
3036 Cvar_RegisterVariable(&r_damageblur);
3037 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3038 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3039 Cvar_RegisterVariable(&r_equalize_entities_by);
3040 Cvar_RegisterVariable(&r_equalize_entities_to);
3041 Cvar_RegisterVariable(&r_animcache);
3042 Cvar_RegisterVariable(&r_depthfirst);
3043 Cvar_RegisterVariable(&r_useinfinitefarclip);
3044 Cvar_RegisterVariable(&r_farclip_base);
3045 Cvar_RegisterVariable(&r_farclip_world);
3046 Cvar_RegisterVariable(&r_nearclip);
3047 Cvar_RegisterVariable(&r_showbboxes);
3048 Cvar_RegisterVariable(&r_showsurfaces);
3049 Cvar_RegisterVariable(&r_showtris);
3050 Cvar_RegisterVariable(&r_shownormals);
3051 Cvar_RegisterVariable(&r_showlighting);
3052 Cvar_RegisterVariable(&r_showshadowvolumes);
3053 Cvar_RegisterVariable(&r_showcollisionbrushes);
3054 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3055 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3056 Cvar_RegisterVariable(&r_showdisabledepthtest);
3057 Cvar_RegisterVariable(&r_drawportals);
3058 Cvar_RegisterVariable(&r_drawentities);
3059 Cvar_RegisterVariable(&r_cullentities_trace);
3060 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3061 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3062 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3063 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3064 Cvar_RegisterVariable(&r_drawviewmodel);
3065 Cvar_RegisterVariable(&r_speeds);
3066 Cvar_RegisterVariable(&r_fullbrights);
3067 Cvar_RegisterVariable(&r_wateralpha);
3068 Cvar_RegisterVariable(&r_dynamic);
3069 Cvar_RegisterVariable(&r_fullbright);
3070 Cvar_RegisterVariable(&r_shadows);
3071 Cvar_RegisterVariable(&r_shadows_darken);
3072 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3073 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3074 Cvar_RegisterVariable(&r_shadows_throwdistance);
3075 Cvar_RegisterVariable(&r_shadows_throwdirection);
3076 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3077 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3078 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3079 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3080 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3081 Cvar_RegisterVariable(&r_fog_exp2);
3082 Cvar_RegisterVariable(&r_drawfog);
3083 Cvar_RegisterVariable(&r_textureunits);
3084 Cvar_RegisterVariable(&r_glsl);
3085 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3086 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3087 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3088 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3089 Cvar_RegisterVariable(&r_glsl_postprocess);
3090 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3091 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3092 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3093 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3094 Cvar_RegisterVariable(&r_glsl_usegeneric);
3095 Cvar_RegisterVariable(&r_water);
3096 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3097 Cvar_RegisterVariable(&r_water_clippingplanebias);
3098 Cvar_RegisterVariable(&r_water_refractdistort);
3099 Cvar_RegisterVariable(&r_water_reflectdistort);
3100 Cvar_RegisterVariable(&r_lerpsprites);
3101 Cvar_RegisterVariable(&r_lerpmodels);
3102 Cvar_RegisterVariable(&r_lerplightstyles);
3103 Cvar_RegisterVariable(&r_waterscroll);
3104 Cvar_RegisterVariable(&r_bloom);
3105 Cvar_RegisterVariable(&r_bloom_colorscale);
3106 Cvar_RegisterVariable(&r_bloom_brighten);
3107 Cvar_RegisterVariable(&r_bloom_blur);
3108 Cvar_RegisterVariable(&r_bloom_resolution);
3109 Cvar_RegisterVariable(&r_bloom_colorexponent);
3110 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3111 Cvar_RegisterVariable(&r_hdr);
3112 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3113 Cvar_RegisterVariable(&r_hdr_glowintensity);
3114 Cvar_RegisterVariable(&r_hdr_range);
3115 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3116 Cvar_RegisterVariable(&developer_texturelogging);
3117 Cvar_RegisterVariable(&gl_lightmaps);
3118 Cvar_RegisterVariable(&r_test);
3119 Cvar_RegisterVariable(&r_batchmode);
3120 Cvar_RegisterVariable(&r_glsl_saturation);
3121 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3122 Cvar_SetValue("r_fullbrights", 0);
3123 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3125 Cvar_RegisterVariable(&r_track_sprites);
3126 Cvar_RegisterVariable(&r_track_sprites_flags);
3127 Cvar_RegisterVariable(&r_track_sprites_scalew);
3128 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3131 extern void R_Textures_Init(void);
3132 extern void GL_Draw_Init(void);
3133 extern void GL_Main_Init(void);
3134 extern void R_Shadow_Init(void);
3135 extern void R_Sky_Init(void);
3136 extern void GL_Surf_Init(void);
3137 extern void R_Particles_Init(void);
3138 extern void R_Explosion_Init(void);
3139 extern void gl_backend_init(void);
3140 extern void Sbar_Init(void);
3141 extern void R_LightningBeams_Init(void);
3142 extern void Mod_RenderInit(void);
3144 void Render_Init(void)
3156 R_LightningBeams_Init();
3165 extern char *ENGINE_EXTENSIONS;
3168 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3169 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3170 gl_version = (const char *)qglGetString(GL_VERSION);
3171 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3175 if (!gl_platformextensions)
3176 gl_platformextensions = "";
3178 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3179 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3180 Con_Printf("GL_VERSION: %s\n", gl_version);
3181 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3182 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3184 VID_CheckExtensions();
3186 // LordHavoc: report supported extensions
3187 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3189 // clear to black (loading plaque will be seen over this)
3191 qglClearColor(0,0,0,1);CHECKGLERROR
3192 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3195 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3199 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3201 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3204 p = r_refdef.view.frustum + i;
3209 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3213 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3217 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3221 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3225 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3229 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3233 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3237 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3245 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3249 for (i = 0;i < numplanes;i++)
3256 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3260 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3264 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3268 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3272 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3276 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3280 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3284 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3292 //==================================================================================
3294 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3297 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3298 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3299 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3302 typedef struct r_animcache_entity_s
3309 qboolean wantnormals;
3310 qboolean wanttangents;
3312 r_animcache_entity_t;
3314 typedef struct r_animcache_s
3316 r_animcache_entity_t entity[MAX_EDICTS];
3322 static r_animcache_t r_animcachestate;
3324 void R_AnimCache_Free(void)
3327 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3329 r_animcachestate.entity[idx].maxvertices = 0;
3330 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3331 r_animcachestate.entity[idx].vertex3f = NULL;
3332 r_animcachestate.entity[idx].normal3f = NULL;
3333 r_animcachestate.entity[idx].svector3f = NULL;
3334 r_animcachestate.entity[idx].tvector3f = NULL;
3336 r_animcachestate.currentindex = 0;
3337 r_animcachestate.maxindex = 0;
3340 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3344 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3346 if (cache->maxvertices >= numvertices)
3349 // Release existing memory
3350 if (cache->vertex3f)
3351 Mem_Free(cache->vertex3f);
3353 // Pad by 1024 verts
3354 cache->maxvertices = (numvertices + 1023) & ~1023;
3355 arraySize = cache->maxvertices * 3;
3357 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3358 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3359 r_animcachestate.entity[cacheIdx].vertex3f = base;
3360 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3361 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3362 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3364 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3367 void R_AnimCache_NewFrame(void)
3371 if (r_animcache.integer && r_drawentities.integer)
3372 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3373 else if (r_animcachestate.maxindex)
3376 r_animcachestate.currentindex = 0;
3378 for (i = 0;i < r_refdef.scene.numentities;i++)
3379 r_refdef.scene.entities[i]->animcacheindex = -1;
3382 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3384 dp_model_t *model = ent->model;
3385 r_animcache_entity_t *c;
3386 // see if it's already cached this frame
3387 if (ent->animcacheindex >= 0)
3389 // add normals/tangents if needed
3390 c = r_animcachestate.entity + ent->animcacheindex;
3392 wantnormals = false;
3393 if (c->wanttangents)
3394 wanttangents = false;
3395 if (wantnormals || wanttangents)
3396 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3400 // see if this ent is worth caching
3401 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3403 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3405 // assign it a cache entry and make sure the arrays are big enough
3406 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3407 ent->animcacheindex = r_animcachestate.currentindex++;
3408 c = r_animcachestate.entity + ent->animcacheindex;
3409 c->wantnormals = wantnormals;
3410 c->wanttangents = wanttangents;
3411 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3416 void R_AnimCache_CacheVisibleEntities(void)
3419 qboolean wantnormals;
3420 qboolean wanttangents;
3422 if (!r_animcachestate.maxindex)
3425 wantnormals = !r_showsurfaces.integer;
3426 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3428 // TODO: thread this?
3430 for (i = 0;i < r_refdef.scene.numentities;i++)
3432 if (!r_refdef.viewcache.entityvisible[i])
3434 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3438 //==================================================================================
3440 static void R_View_UpdateEntityLighting (void)
3443 entity_render_t *ent;
3444 vec3_t tempdiffusenormal, avg;
3445 vec_t f, fa, fd, fdd;
3447 for (i = 0;i < r_refdef.scene.numentities;i++)
3449 ent = r_refdef.scene.entities[i];
3451 // skip unseen models
3452 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3456 if (ent->model && ent->model->brush.num_leafs)
3458 // TODO: use modellight for r_ambient settings on world?
3459 VectorSet(ent->modellight_ambient, 0, 0, 0);
3460 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3461 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3465 // fetch the lighting from the worldmodel data
3466 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));
3467 VectorClear(ent->modellight_diffuse);
3468 VectorClear(tempdiffusenormal);
3469 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3472 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3473 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3474 if(ent->flags & RENDER_EQUALIZE)
3476 // first fix up ambient lighting...
3477 if(r_equalize_entities_minambient.value > 0)
3479 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3482 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3483 if(fa < r_equalize_entities_minambient.value * fd)
3486 // fa'/fd' = minambient
3487 // fa'+0.25*fd' = fa+0.25*fd
3489 // fa' = fd' * minambient
3490 // fd'*(0.25+minambient) = fa+0.25*fd
3492 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3493 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3495 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3496 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
3497 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3498 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3503 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3505 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3506 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3509 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3510 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3511 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3517 VectorSet(ent->modellight_ambient, 1, 1, 1);
3519 // move the light direction into modelspace coordinates for lighting code
3520 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3521 if(VectorLength2(ent->modellight_lightdir) == 0)
3522 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3523 VectorNormalize(ent->modellight_lightdir);
3527 #define MAX_LINEOFSIGHTTRACES 64
3529 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3532 vec3_t boxmins, boxmaxs;
3535 dp_model_t *model = r_refdef.scene.worldmodel;
3537 if (!model || !model->brush.TraceLineOfSight)
3540 // expand the box a little
3541 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3542 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3543 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3544 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3545 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3546 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3549 VectorCopy(eye, start);
3550 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3551 if (model->brush.TraceLineOfSight(model, start, end))
3554 // try various random positions
3555 for (i = 0;i < numsamples;i++)
3557 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3558 if (model->brush.TraceLineOfSight(model, start, end))
3566 static void R_View_UpdateEntityVisible (void)
3571 entity_render_t *ent;
3573 if (!r_drawentities.integer)
3576 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3577 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3579 // worldmodel can check visibility
3580 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3581 for (i = 0;i < r_refdef.scene.numentities;i++)
3583 ent = r_refdef.scene.entities[i];
3584 if (!(ent->flags & renderimask))
3585 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)))
3586 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))
3587 r_refdef.viewcache.entityvisible[i] = true;
3589 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3591 for (i = 0;i < r_refdef.scene.numentities;i++)
3593 ent = r_refdef.scene.entities[i];
3594 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3596 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3598 continue; // temp entities do pvs only
3599 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3600 ent->last_trace_visibility = realtime;
3601 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3602 r_refdef.viewcache.entityvisible[i] = 0;
3609 // no worldmodel or it can't check visibility
3610 for (i = 0;i < r_refdef.scene.numentities;i++)
3612 ent = r_refdef.scene.entities[i];
3613 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));
3618 /// only used if skyrendermasked, and normally returns false
3619 int R_DrawBrushModelsSky (void)
3622 entity_render_t *ent;
3624 if (!r_drawentities.integer)
3628 for (i = 0;i < r_refdef.scene.numentities;i++)
3630 if (!r_refdef.viewcache.entityvisible[i])
3632 ent = r_refdef.scene.entities[i];
3633 if (!ent->model || !ent->model->DrawSky)
3635 ent->model->DrawSky(ent);
3641 static void R_DrawNoModel(entity_render_t *ent);
3642 static void R_DrawModels(void)
3645 entity_render_t *ent;
3647 if (!r_drawentities.integer)
3650 for (i = 0;i < r_refdef.scene.numentities;i++)
3652 if (!r_refdef.viewcache.entityvisible[i])
3654 ent = r_refdef.scene.entities[i];
3655 r_refdef.stats.entities++;
3656 if (ent->model && ent->model->Draw != NULL)
3657 ent->model->Draw(ent);
3663 static void R_DrawModelsDepth(void)
3666 entity_render_t *ent;
3668 if (!r_drawentities.integer)
3671 for (i = 0;i < r_refdef.scene.numentities;i++)
3673 if (!r_refdef.viewcache.entityvisible[i])
3675 ent = r_refdef.scene.entities[i];
3676 if (ent->model && ent->model->DrawDepth != NULL)
3677 ent->model->DrawDepth(ent);
3681 static void R_DrawModelsDebug(void)
3684 entity_render_t *ent;
3686 if (!r_drawentities.integer)
3689 for (i = 0;i < r_refdef.scene.numentities;i++)
3691 if (!r_refdef.viewcache.entityvisible[i])
3693 ent = r_refdef.scene.entities[i];
3694 if (ent->model && ent->model->DrawDebug != NULL)
3695 ent->model->DrawDebug(ent);
3699 static void R_DrawModelsAddWaterPlanes(void)
3702 entity_render_t *ent;
3704 if (!r_drawentities.integer)
3707 for (i = 0;i < r_refdef.scene.numentities;i++)
3709 if (!r_refdef.viewcache.entityvisible[i])
3711 ent = r_refdef.scene.entities[i];
3712 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3713 ent->model->DrawAddWaterPlanes(ent);
3717 static void R_DrawModelDecals_Entity(entity_render_t *ent);
3718 static void R_DecalSystem_ApplySplatEntitiesQueue(void);
3719 static void R_DrawModelDecals(void)
3722 entity_render_t *ent;
3724 R_DecalSystem_ApplySplatEntitiesQueue();
3726 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
3728 if (!r_drawentities.integer || r_showsurfaces.integer)
3731 for (i = 0;i < r_refdef.scene.numentities;i++)
3733 if (!r_refdef.viewcache.entityvisible[i])
3735 ent = r_refdef.scene.entities[i];
3736 r_refdef.stats.entities++;
3737 if (ent->decalsystem.numdecals)
3738 R_DrawModelDecals_Entity(ent);
3742 static void R_View_SetFrustum(void)
3745 double slopex, slopey;
3746 vec3_t forward, left, up, origin;
3748 // we can't trust r_refdef.view.forward and friends in reflected scenes
3749 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3752 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3753 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3754 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3755 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3756 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3757 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3758 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3759 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3760 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3761 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3762 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3763 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3767 zNear = r_refdef.nearclip;
3768 nudge = 1.0 - 1.0 / (1<<23);
3769 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3770 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3771 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3772 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3773 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3774 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3775 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3776 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3782 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3783 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3784 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3785 r_refdef.view.frustum[0].dist = m[15] - m[12];
3787 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3788 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3789 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3790 r_refdef.view.frustum[1].dist = m[15] + m[12];
3792 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3793 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3794 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3795 r_refdef.view.frustum[2].dist = m[15] - m[13];
3797 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3798 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3799 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3800 r_refdef.view.frustum[3].dist = m[15] + m[13];
3802 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3803 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3804 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3805 r_refdef.view.frustum[4].dist = m[15] - m[14];
3807 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3808 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3809 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3810 r_refdef.view.frustum[5].dist = m[15] + m[14];
3813 if (r_refdef.view.useperspective)
3815 slopex = 1.0 / r_refdef.view.frustum_x;
3816 slopey = 1.0 / r_refdef.view.frustum_y;
3817 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3818 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3819 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3820 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3821 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3823 // Leaving those out was a mistake, those were in the old code, and they
3824 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3825 // I couldn't reproduce it after adding those normalizations. --blub
3826 VectorNormalize(r_refdef.view.frustum[0].normal);
3827 VectorNormalize(r_refdef.view.frustum[1].normal);
3828 VectorNormalize(r_refdef.view.frustum[2].normal);
3829 VectorNormalize(r_refdef.view.frustum[3].normal);
3831 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3832 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]);
3833 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]);
3834 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]);
3835 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]);
3837 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3838 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3839 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3840 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3841 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3845 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3846 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3847 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3848 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3849 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3850 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3851 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3852 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3853 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3854 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3856 r_refdef.view.numfrustumplanes = 5;
3858 if (r_refdef.view.useclipplane)
3860 r_refdef.view.numfrustumplanes = 6;
3861 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3864 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3865 PlaneClassify(r_refdef.view.frustum + i);
3867 // LordHavoc: note to all quake engine coders, Quake had a special case
3868 // for 90 degrees which assumed a square view (wrong), so I removed it,
3869 // Quake2 has it disabled as well.
3871 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3872 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3873 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3874 //PlaneClassify(&frustum[0]);
3876 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3877 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3878 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3879 //PlaneClassify(&frustum[1]);
3881 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3882 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3883 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3884 //PlaneClassify(&frustum[2]);
3886 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3887 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3888 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3889 //PlaneClassify(&frustum[3]);
3892 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3893 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3894 //PlaneClassify(&frustum[4]);
3897 void R_View_Update(void)
3899 R_Main_ResizeViewCache();
3900 R_View_SetFrustum();
3901 R_View_WorldVisibility(r_refdef.view.useclipplane);
3902 R_View_UpdateEntityVisible();
3903 R_View_UpdateEntityLighting();
3906 void R_SetupView(qboolean allowwaterclippingplane)
3908 const double *customclipplane = NULL;
3910 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3912 // LordHavoc: couldn't figure out how to make this approach the
3913 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3914 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3915 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3916 dist = r_refdef.view.clipplane.dist;
3917 plane[0] = r_refdef.view.clipplane.normal[0];
3918 plane[1] = r_refdef.view.clipplane.normal[1];
3919 plane[2] = r_refdef.view.clipplane.normal[2];
3921 customclipplane = plane;
3924 if (!r_refdef.view.useperspective)
3925 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);
3926 else if (gl_stencil && r_useinfinitefarclip.integer)
3927 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);
3929 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);
3930 R_SetViewport(&r_refdef.view.viewport);
3933 void R_ResetViewRendering2D(void)
3935 r_viewport_t viewport;
3938 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3939 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);
3940 R_SetViewport(&viewport);
3941 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3942 GL_Color(1, 1, 1, 1);
3943 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3944 GL_BlendFunc(GL_ONE, GL_ZERO);
3945 GL_AlphaTest(false);
3946 GL_ScissorTest(false);
3947 GL_DepthMask(false);
3948 GL_DepthRange(0, 1);
3949 GL_DepthTest(false);
3950 R_Mesh_Matrix(&identitymatrix);
3951 R_Mesh_ResetTextureState();
3952 GL_PolygonOffset(0, 0);
3953 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3954 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3955 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3956 qglStencilMask(~0);CHECKGLERROR
3957 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3958 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3959 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3960 R_SetupGenericShader(true);
3963 void R_ResetViewRendering3D(void)
3968 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3969 GL_Color(1, 1, 1, 1);
3970 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3971 GL_BlendFunc(GL_ONE, GL_ZERO);
3972 GL_AlphaTest(false);
3973 GL_ScissorTest(true);
3975 GL_DepthRange(0, 1);
3977 R_Mesh_Matrix(&identitymatrix);
3978 R_Mesh_ResetTextureState();
3979 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3980 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3981 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3982 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3983 qglStencilMask(~0);CHECKGLERROR
3984 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3985 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3986 GL_CullFace(r_refdef.view.cullface_back);
3987 R_SetupGenericShader(true);
3990 void R_RenderScene(void);
3991 void R_RenderWaterPlanes(void);
3993 static void R_Water_StartFrame(void)
3996 int waterwidth, waterheight, texturewidth, textureheight;
3997 r_waterstate_waterplane_t *p;
3999 // set waterwidth and waterheight to the water resolution that will be
4000 // used (often less than the screen resolution for faster rendering)
4001 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
4002 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
4004 // calculate desired texture sizes
4005 // can't use water if the card does not support the texture size
4006 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
4007 texturewidth = textureheight = waterwidth = waterheight = 0;
4008 else if (gl_support_arb_texture_non_power_of_two)
4010 texturewidth = waterwidth;
4011 textureheight = waterheight;
4015 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4016 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4019 // allocate textures as needed
4020 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4022 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4023 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4025 if (p->texture_refraction)
4026 R_FreeTexture(p->texture_refraction);
4027 p->texture_refraction = NULL;
4028 if (p->texture_reflection)
4029 R_FreeTexture(p->texture_reflection);
4030 p->texture_reflection = NULL;
4032 memset(&r_waterstate, 0, sizeof(r_waterstate));
4033 r_waterstate.texturewidth = texturewidth;
4034 r_waterstate.textureheight = textureheight;
4037 if (r_waterstate.texturewidth)
4039 r_waterstate.enabled = true;
4041 // when doing a reduced render (HDR) we want to use a smaller area
4042 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4043 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4045 // set up variables that will be used in shader setup
4046 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4047 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4048 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4049 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4052 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4053 r_waterstate.numwaterplanes = 0;
4056 void R_Water_AddWaterPlane(msurface_t *surface)
4058 int triangleindex, planeindex;
4064 r_waterstate_waterplane_t *p;
4065 texture_t *t = R_GetCurrentTexture(surface->texture);
4066 // just use the first triangle with a valid normal for any decisions
4067 VectorClear(normal);
4068 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4070 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4071 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4072 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4073 TriangleNormal(vert[0], vert[1], vert[2], normal);
4074 if (VectorLength2(normal) >= 0.001)
4078 VectorCopy(normal, plane.normal);
4079 VectorNormalize(plane.normal);
4080 plane.dist = DotProduct(vert[0], plane.normal);
4081 PlaneClassify(&plane);
4082 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4084 // skip backfaces (except if nocullface is set)
4085 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4087 VectorNegate(plane.normal, plane.normal);
4089 PlaneClassify(&plane);
4093 // find a matching plane if there is one
4094 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4095 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4097 if (planeindex >= r_waterstate.maxwaterplanes)
4098 return; // nothing we can do, out of planes
4100 // if this triangle does not fit any known plane rendered this frame, add one
4101 if (planeindex >= r_waterstate.numwaterplanes)
4103 // store the new plane
4104 r_waterstate.numwaterplanes++;
4106 // clear materialflags and pvs
4107 p->materialflags = 0;
4108 p->pvsvalid = false;
4110 // merge this surface's materialflags into the waterplane
4111 p->materialflags |= t->currentmaterialflags;
4112 // merge this surface's PVS into the waterplane
4113 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4114 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4115 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4117 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4122 static void R_Water_ProcessPlanes(void)
4124 r_refdef_view_t originalview;
4125 r_refdef_view_t myview;
4127 r_waterstate_waterplane_t *p;
4129 originalview = r_refdef.view;
4131 // make sure enough textures are allocated
4132 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4134 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4136 if (!p->texture_refraction)
4137 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);
4138 if (!p->texture_refraction)
4142 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4144 if (!p->texture_reflection)
4145 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);
4146 if (!p->texture_reflection)
4152 r_refdef.view = originalview;
4153 r_refdef.view.showdebug = false;
4154 r_refdef.view.width = r_waterstate.waterwidth;
4155 r_refdef.view.height = r_waterstate.waterheight;
4156 r_refdef.view.useclipplane = true;
4157 myview = r_refdef.view;
4158 r_waterstate.renderingscene = true;
4159 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4161 // render the normal view scene and copy into texture
4162 // (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)
4163 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4165 r_refdef.view = myview;
4166 r_refdef.view.clipplane = p->plane;
4167 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4168 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4169 PlaneClassify(&r_refdef.view.clipplane);
4171 R_ResetViewRendering3D();
4172 R_ClearScreen(r_refdef.fogenabled);
4176 // copy view into the screen texture
4177 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4178 GL_ActiveTexture(0);
4180 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
4183 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4185 r_refdef.view = myview;
4186 // render reflected scene and copy into texture
4187 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4188 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4189 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4190 r_refdef.view.clipplane = p->plane;
4191 // reverse the cullface settings for this render
4192 r_refdef.view.cullface_front = GL_FRONT;
4193 r_refdef.view.cullface_back = GL_BACK;
4194 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4196 r_refdef.view.usecustompvs = true;
4198 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4200 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4203 R_ResetViewRendering3D();
4204 R_ClearScreen(r_refdef.fogenabled);
4208 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4209 GL_ActiveTexture(0);
4211 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
4214 r_waterstate.renderingscene = false;
4215 r_refdef.view = originalview;
4216 R_ResetViewRendering3D();
4217 R_ClearScreen(r_refdef.fogenabled);
4221 r_refdef.view = originalview;
4222 r_waterstate.renderingscene = false;
4223 Cvar_SetValueQuick(&r_water, 0);
4224 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4228 void R_Bloom_StartFrame(void)
4230 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4232 // set bloomwidth and bloomheight to the bloom resolution that will be
4233 // used (often less than the screen resolution for faster rendering)
4234 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4235 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4236 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4237 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
4238 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
4240 // calculate desired texture sizes
4241 if (gl_support_arb_texture_non_power_of_two)
4243 screentexturewidth = r_refdef.view.width;
4244 screentextureheight = r_refdef.view.height;
4245 bloomtexturewidth = r_bloomstate.bloomwidth;
4246 bloomtextureheight = r_bloomstate.bloomheight;
4250 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4251 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4252 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4253 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4256 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
4258 Cvar_SetValueQuick(&r_hdr, 0);
4259 Cvar_SetValueQuick(&r_bloom, 0);
4260 Cvar_SetValueQuick(&r_motionblur, 0);
4261 Cvar_SetValueQuick(&r_damageblur, 0);
4264 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)))
4265 screentexturewidth = screentextureheight = 0;
4266 if (!r_hdr.integer && !r_bloom.integer)
4267 bloomtexturewidth = bloomtextureheight = 0;
4269 // allocate textures as needed
4270 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4272 if (r_bloomstate.texture_screen)
4273 R_FreeTexture(r_bloomstate.texture_screen);
4274 r_bloomstate.texture_screen = NULL;
4275 r_bloomstate.screentexturewidth = screentexturewidth;
4276 r_bloomstate.screentextureheight = screentextureheight;
4277 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4278 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);
4280 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4282 if (r_bloomstate.texture_bloom)
4283 R_FreeTexture(r_bloomstate.texture_bloom);
4284 r_bloomstate.texture_bloom = NULL;
4285 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4286 r_bloomstate.bloomtextureheight = bloomtextureheight;
4287 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4288 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);
4291 // when doing a reduced render (HDR) we want to use a smaller area
4292 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4293 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4294 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4295 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4296 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4298 // set up a texcoord array for the full resolution screen image
4299 // (we have to keep this around to copy back during final render)
4300 r_bloomstate.screentexcoord2f[0] = 0;
4301 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4302 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4303 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4304 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4305 r_bloomstate.screentexcoord2f[5] = 0;
4306 r_bloomstate.screentexcoord2f[6] = 0;
4307 r_bloomstate.screentexcoord2f[7] = 0;
4309 // set up a texcoord array for the reduced resolution bloom image
4310 // (which will be additive blended over the screen image)
4311 r_bloomstate.bloomtexcoord2f[0] = 0;
4312 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4313 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4314 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4315 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4316 r_bloomstate.bloomtexcoord2f[5] = 0;
4317 r_bloomstate.bloomtexcoord2f[6] = 0;
4318 r_bloomstate.bloomtexcoord2f[7] = 0;
4320 if (r_hdr.integer || r_bloom.integer)
4322 r_bloomstate.enabled = true;
4323 r_bloomstate.hdr = r_hdr.integer != 0;
4326 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);
4329 void R_Bloom_CopyBloomTexture(float colorscale)
4331 r_refdef.stats.bloom++;
4333 // scale down screen texture to the bloom texture size
4335 R_SetViewport(&r_bloomstate.viewport);
4336 GL_BlendFunc(GL_ONE, GL_ZERO);
4337 GL_Color(colorscale, colorscale, colorscale, 1);
4338 // TODO: optimize with multitexture or GLSL
4339 R_SetupGenericShader(true);
4340 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4341 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4342 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4343 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4345 // we now have a bloom image in the framebuffer
4346 // copy it into the bloom image texture for later processing
4347 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4348 GL_ActiveTexture(0);
4350 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4351 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4354 void R_Bloom_CopyHDRTexture(void)
4356 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4357 GL_ActiveTexture(0);
4359 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
4360 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4363 void R_Bloom_MakeTexture(void)
4366 float xoffset, yoffset, r, brighten;
4368 r_refdef.stats.bloom++;
4370 R_ResetViewRendering2D();
4371 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4372 R_Mesh_ColorPointer(NULL, 0, 0);
4373 R_SetupGenericShader(true);
4375 // we have a bloom image in the framebuffer
4377 R_SetViewport(&r_bloomstate.viewport);
4379 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4382 r = bound(0, r_bloom_colorexponent.value / x, 1);
4383 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4384 GL_Color(r, r, r, 1);
4385 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4386 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4387 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4388 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4390 // copy the vertically blurred bloom view to a texture
4391 GL_ActiveTexture(0);
4393 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4394 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4397 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4398 brighten = r_bloom_brighten.value;
4400 brighten *= r_hdr_range.value;
4401 brighten = sqrt(brighten);
4403 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4404 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4405 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4407 for (dir = 0;dir < 2;dir++)
4409 // blend on at multiple vertical offsets to achieve a vertical blur
4410 // TODO: do offset blends using GLSL
4411 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4412 GL_BlendFunc(GL_ONE, GL_ZERO);
4413 for (x = -range;x <= range;x++)
4415 if (!dir){xoffset = 0;yoffset = x;}
4416 else {xoffset = x;yoffset = 0;}
4417 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4418 yoffset /= (float)r_bloomstate.bloomtextureheight;
4419 // compute a texcoord array with the specified x and y offset
4420 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4421 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4422 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4423 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4424 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4425 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4426 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4427 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4428 // this r value looks like a 'dot' particle, fading sharply to
4429 // black at the edges
4430 // (probably not realistic but looks good enough)
4431 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4432 //r = brighten/(range*2+1);
4433 r = brighten / (range * 2 + 1);
4435 r *= (1 - x*x/(float)(range*range));
4436 GL_Color(r, r, r, 1);
4437 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4438 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4439 GL_BlendFunc(GL_ONE, GL_ONE);
4442 // copy the vertically blurred bloom view to a texture
4443 GL_ActiveTexture(0);
4445 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4446 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4449 // apply subtract last
4450 // (just like it would be in a GLSL shader)
4451 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4453 GL_BlendFunc(GL_ONE, GL_ZERO);
4454 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4455 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4456 GL_Color(1, 1, 1, 1);
4457 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4458 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4460 GL_BlendFunc(GL_ONE, GL_ONE);
4461 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4462 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4463 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4464 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4465 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4466 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4467 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4469 // copy the darkened bloom view to a texture
4470 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4471 GL_ActiveTexture(0);
4473 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4474 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4478 void R_HDR_RenderBloomTexture(void)
4480 int oldwidth, oldheight;
4481 float oldcolorscale;
4483 oldcolorscale = r_refdef.view.colorscale;
4484 oldwidth = r_refdef.view.width;
4485 oldheight = r_refdef.view.height;
4486 r_refdef.view.width = r_bloomstate.bloomwidth;
4487 r_refdef.view.height = r_bloomstate.bloomheight;
4489 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4490 // TODO: add exposure compensation features
4491 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4493 r_refdef.view.showdebug = false;
4494 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4496 R_ResetViewRendering3D();
4498 R_ClearScreen(r_refdef.fogenabled);
4499 if (r_timereport_active)
4500 R_TimeReport("HDRclear");
4503 if (r_timereport_active)
4504 R_TimeReport("visibility");
4506 // only do secondary renders with HDR if r_hdr is 2 or higher
4507 r_waterstate.numwaterplanes = 0;
4508 if (r_waterstate.enabled && r_hdr.integer >= 2)
4509 R_RenderWaterPlanes();
4511 r_refdef.view.showdebug = true;
4513 r_waterstate.numwaterplanes = 0;
4515 R_ResetViewRendering2D();
4517 R_Bloom_CopyHDRTexture();
4518 R_Bloom_MakeTexture();
4520 // restore the view settings
4521 r_refdef.view.width = oldwidth;
4522 r_refdef.view.height = oldheight;
4523 r_refdef.view.colorscale = oldcolorscale;
4525 R_ResetViewRendering3D();
4527 R_ClearScreen(r_refdef.fogenabled);
4528 if (r_timereport_active)
4529 R_TimeReport("viewclear");
4532 static void R_BlendView(void)
4534 if (r_bloomstate.texture_screen)
4536 // make sure the buffer is available
4537 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4539 R_ResetViewRendering2D();
4540 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4541 R_Mesh_ColorPointer(NULL, 0, 0);
4542 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4543 GL_ActiveTexture(0);CHECKGLERROR
4545 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4547 // declare variables
4549 static float avgspeed;
4551 speed = VectorLength(cl.movement_velocity);
4553 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4554 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4556 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4557 speed = bound(0, speed, 1);
4558 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4560 // calculate values into a standard alpha
4561 cl.motionbluralpha = 1 - exp(-
4563 (r_motionblur.value * speed / 80)
4565 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4568 max(0.0001, cl.time - cl.oldtime) // fps independent
4571 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4572 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4574 if (cl.motionbluralpha > 0)
4576 R_SetupGenericShader(true);
4577 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4578 GL_Color(1, 1, 1, cl.motionbluralpha);
4579 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4580 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4581 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4582 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4586 // copy view into the screen texture
4587 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
4588 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4591 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4593 unsigned int permutation =
4594 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4595 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4596 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4597 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4598 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4600 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4602 // render simple bloom effect
4603 // copy the screen and shrink it and darken it for the bloom process
4604 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4605 // make the bloom texture
4606 R_Bloom_MakeTexture();
4609 R_ResetViewRendering2D();
4610 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4611 R_Mesh_ColorPointer(NULL, 0, 0);
4612 GL_Color(1, 1, 1, 1);
4613 GL_BlendFunc(GL_ONE, GL_ZERO);
4614 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4615 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4616 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4617 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4618 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4619 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4620 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4621 if (r_glsl_permutation->loc_TintColor >= 0)
4622 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4623 if (r_glsl_permutation->loc_ClientTime >= 0)
4624 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4625 if (r_glsl_permutation->loc_PixelSize >= 0)
4626 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4627 if (r_glsl_permutation->loc_UserVec1 >= 0)
4629 float a=0, b=0, c=0, d=0;
4630 #if _MSC_VER >= 1400
4631 #define sscanf sscanf_s
4633 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4634 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4636 if (r_glsl_permutation->loc_UserVec2 >= 0)
4638 float a=0, b=0, c=0, d=0;
4639 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4640 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4642 if (r_glsl_permutation->loc_UserVec3 >= 0)
4644 float a=0, b=0, c=0, d=0;
4645 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4646 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4648 if (r_glsl_permutation->loc_UserVec4 >= 0)
4650 float a=0, b=0, c=0, d=0;
4651 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4652 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4654 if (r_glsl_permutation->loc_Saturation >= 0)
4655 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4656 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4657 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4663 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4665 // render high dynamic range bloom effect
4666 // the bloom texture was made earlier this render, so we just need to
4667 // blend it onto the screen...
4668 R_ResetViewRendering2D();
4669 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4670 R_Mesh_ColorPointer(NULL, 0, 0);
4671 R_SetupGenericShader(true);
4672 GL_Color(1, 1, 1, 1);
4673 GL_BlendFunc(GL_ONE, GL_ONE);
4674 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4675 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4676 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4677 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4679 else if (r_bloomstate.texture_bloom)
4681 // render simple bloom effect
4682 // copy the screen and shrink it and darken it for the bloom process
4683 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4684 // make the bloom texture
4685 R_Bloom_MakeTexture();
4686 // put the original screen image back in place and blend the bloom
4688 R_ResetViewRendering2D();
4689 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4690 R_Mesh_ColorPointer(NULL, 0, 0);
4691 GL_Color(1, 1, 1, 1);
4692 GL_BlendFunc(GL_ONE, GL_ZERO);
4693 // do both in one pass if possible
4694 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4695 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4696 if (r_textureunits.integer >= 2 && gl_combine.integer)
4698 R_SetupGenericTwoTextureShader(GL_ADD);
4699 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4700 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4704 R_SetupGenericShader(true);
4705 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4706 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4707 // now blend on the bloom texture
4708 GL_BlendFunc(GL_ONE, GL_ONE);
4709 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4710 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4712 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4713 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4715 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4717 // apply a color tint to the whole view
4718 R_ResetViewRendering2D();
4719 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4720 R_Mesh_ColorPointer(NULL, 0, 0);
4721 R_SetupGenericShader(false);
4722 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4723 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4724 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4728 matrix4x4_t r_waterscrollmatrix;
4730 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4732 if (r_refdef.fog_density)
4734 r_refdef.fogcolor[0] = r_refdef.fog_red;
4735 r_refdef.fogcolor[1] = r_refdef.fog_green;
4736 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4738 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4739 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4740 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4741 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4745 VectorCopy(r_refdef.fogcolor, fogvec);
4746 // color.rgb *= ContrastBoost * SceneBrightness;
4747 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4748 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4749 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4750 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4755 void R_UpdateVariables(void)
4759 r_refdef.scene.ambient = r_ambient.value;
4761 r_refdef.farclip = r_farclip_base.value;
4762 if (r_refdef.scene.worldmodel)
4763 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
4764 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4766 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4767 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4768 r_refdef.polygonfactor = 0;
4769 r_refdef.polygonoffset = 0;
4770 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4771 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4773 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4774 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4775 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4776 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4777 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4778 if (r_showsurfaces.integer)
4780 r_refdef.scene.rtworld = false;
4781 r_refdef.scene.rtworldshadows = false;
4782 r_refdef.scene.rtdlight = false;
4783 r_refdef.scene.rtdlightshadows = false;
4784 r_refdef.lightmapintensity = 0;
4787 if (gamemode == GAME_NEHAHRA)
4789 if (gl_fogenable.integer)
4791 r_refdef.oldgl_fogenable = true;
4792 r_refdef.fog_density = gl_fogdensity.value;
4793 r_refdef.fog_red = gl_fogred.value;
4794 r_refdef.fog_green = gl_foggreen.value;
4795 r_refdef.fog_blue = gl_fogblue.value;
4796 r_refdef.fog_alpha = 1;
4797 r_refdef.fog_start = 0;
4798 r_refdef.fog_end = gl_skyclip.value;
4799 r_refdef.fog_height = 1<<30;
4800 r_refdef.fog_fadedepth = 128;
4802 else if (r_refdef.oldgl_fogenable)
4804 r_refdef.oldgl_fogenable = false;
4805 r_refdef.fog_density = 0;
4806 r_refdef.fog_red = 0;
4807 r_refdef.fog_green = 0;
4808 r_refdef.fog_blue = 0;
4809 r_refdef.fog_alpha = 0;
4810 r_refdef.fog_start = 0;
4811 r_refdef.fog_end = 0;
4812 r_refdef.fog_height = 1<<30;
4813 r_refdef.fog_fadedepth = 128;
4817 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4818 r_refdef.fog_start = max(0, r_refdef.fog_start);
4819 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4821 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4823 if (r_refdef.fog_density && r_drawfog.integer)
4825 r_refdef.fogenabled = true;
4826 // this is the point where the fog reaches 0.9986 alpha, which we
4827 // consider a good enough cutoff point for the texture
4828 // (0.9986 * 256 == 255.6)
4829 if (r_fog_exp2.integer)
4830 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4832 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4833 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4834 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4835 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4836 // fog color was already set
4837 // update the fog texture
4838 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)
4839 R_BuildFogTexture();
4842 r_refdef.fogenabled = false;
4844 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4846 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4848 // build GLSL gamma texture
4849 #define RAMPWIDTH 256
4850 unsigned short ramp[RAMPWIDTH * 3];
4851 unsigned char rampbgr[RAMPWIDTH][4];
4854 r_texture_gammaramps_serial = vid_gammatables_serial;
4856 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4857 for(i = 0; i < RAMPWIDTH; ++i)
4859 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4860 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4861 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4864 if (r_texture_gammaramps)
4866 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4870 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);
4876 // remove GLSL gamma texture
4880 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4881 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4887 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4888 if( scenetype != r_currentscenetype ) {
4889 // store the old scenetype
4890 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4891 r_currentscenetype = scenetype;
4892 // move in the new scene
4893 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4902 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4904 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4905 if( scenetype == r_currentscenetype ) {
4906 return &r_refdef.scene;
4908 return &r_scenes_store[ scenetype ];
4917 void R_RenderView(void)
4919 if (r_timereport_active)
4920 R_TimeReport("start");
4921 r_frame++; // used only by R_GetCurrentTexture
4922 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4924 R_AnimCache_NewFrame();
4926 if (r_refdef.view.isoverlay)
4928 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4929 GL_Clear( GL_DEPTH_BUFFER_BIT );
4930 R_TimeReport("depthclear");
4932 r_refdef.view.showdebug = false;
4934 r_waterstate.enabled = false;
4935 r_waterstate.numwaterplanes = 0;
4943 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4944 return; //Host_Error ("R_RenderView: NULL worldmodel");
4946 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4948 // break apart the view matrix into vectors for various purposes
4949 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4950 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4951 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4952 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4953 // make an inverted copy of the view matrix for tracking sprites
4954 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4956 R_Shadow_UpdateWorldLightSelection();
4958 R_Bloom_StartFrame();
4959 R_Water_StartFrame();
4962 if (r_timereport_active)
4963 R_TimeReport("viewsetup");
4965 R_ResetViewRendering3D();
4967 if (r_refdef.view.clear || r_refdef.fogenabled)
4969 R_ClearScreen(r_refdef.fogenabled);
4970 if (r_timereport_active)
4971 R_TimeReport("viewclear");
4973 r_refdef.view.clear = true;
4975 // this produces a bloom texture to be used in R_BlendView() later
4977 R_HDR_RenderBloomTexture();
4979 r_refdef.view.showdebug = true;
4982 if (r_timereport_active)
4983 R_TimeReport("visibility");
4985 r_waterstate.numwaterplanes = 0;
4986 if (r_waterstate.enabled)
4987 R_RenderWaterPlanes();
4990 r_waterstate.numwaterplanes = 0;
4993 if (r_timereport_active)
4994 R_TimeReport("blendview");
4996 GL_Scissor(0, 0, vid.width, vid.height);
4997 GL_ScissorTest(false);
5001 void R_RenderWaterPlanes(void)
5003 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5005 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5006 if (r_timereport_active)
5007 R_TimeReport("waterworld");
5010 // don't let sound skip if going slow
5011 if (r_refdef.scene.extraupdate)
5014 R_DrawModelsAddWaterPlanes();
5015 if (r_timereport_active)
5016 R_TimeReport("watermodels");
5018 if (r_waterstate.numwaterplanes)
5020 R_Water_ProcessPlanes();
5021 if (r_timereport_active)
5022 R_TimeReport("waterscenes");
5026 extern void R_DrawLightningBeams (void);
5027 extern void VM_CL_AddPolygonsToMeshQueue (void);
5028 extern void R_DrawPortals (void);
5029 extern cvar_t cl_locs_show;
5030 static void R_DrawLocs(void);
5031 static void R_DrawEntityBBoxes(void);
5032 extern cvar_t cl_decals_newsystem;
5033 void R_RenderScene(void)
5035 r_refdef.stats.renders++;
5039 // don't let sound skip if going slow
5040 if (r_refdef.scene.extraupdate)
5043 R_MeshQueue_BeginScene();
5047 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);
5049 if (cl.csqc_vidvars.drawworld)
5051 // don't let sound skip if going slow
5052 if (r_refdef.scene.extraupdate)
5055 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5057 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5058 if (r_timereport_active)
5059 R_TimeReport("worldsky");
5062 if (R_DrawBrushModelsSky() && r_timereport_active)
5063 R_TimeReport("bmodelsky");
5065 if (skyrendermasked && skyrenderlater)
5067 // we have to force off the water clipping plane while rendering sky
5074 R_AnimCache_CacheVisibleEntities();
5076 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5078 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5079 if (r_timereport_active)
5080 R_TimeReport("worlddepth");
5082 if (r_depthfirst.integer >= 2)
5084 R_DrawModelsDepth();
5085 if (r_timereport_active)
5086 R_TimeReport("modeldepth");
5089 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5091 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5092 if (r_timereport_active)
5093 R_TimeReport("world");
5096 // don't let sound skip if going slow
5097 if (r_refdef.scene.extraupdate)
5101 if (r_timereport_active)
5102 R_TimeReport("models");
5104 // don't let sound skip if going slow
5105 if (r_refdef.scene.extraupdate)
5108 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5110 R_DrawModelShadows();
5111 R_ResetViewRendering3D();
5112 // don't let sound skip if going slow
5113 if (r_refdef.scene.extraupdate)
5117 R_ShadowVolumeLighting(false);
5118 if (r_timereport_active)
5119 R_TimeReport("rtlights");
5121 // don't let sound skip if going slow
5122 if (r_refdef.scene.extraupdate)
5125 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5127 R_DrawModelShadows();
5128 R_ResetViewRendering3D();
5129 // don't let sound skip if going slow
5130 if (r_refdef.scene.extraupdate)
5134 if (cl.csqc_vidvars.drawworld)
5136 if (cl_decals_newsystem.integer)
5138 R_DrawModelDecals();
5139 if (r_timereport_active)
5140 R_TimeReport("modeldecals");
5145 if (r_timereport_active)
5146 R_TimeReport("decals");
5150 if (r_timereport_active)
5151 R_TimeReport("particles");
5154 if (r_timereport_active)
5155 R_TimeReport("explosions");
5157 R_DrawLightningBeams();
5158 if (r_timereport_active)
5159 R_TimeReport("lightning");
5162 R_SetupGenericShader(true);
5163 VM_CL_AddPolygonsToMeshQueue();
5165 if (r_refdef.view.showdebug)
5167 if (cl_locs_show.integer)
5170 if (r_timereport_active)
5171 R_TimeReport("showlocs");
5174 if (r_drawportals.integer)
5177 if (r_timereport_active)
5178 R_TimeReport("portals");
5181 if (r_showbboxes.value > 0)
5183 R_DrawEntityBBoxes();
5184 if (r_timereport_active)
5185 R_TimeReport("bboxes");
5189 R_SetupGenericShader(true);
5190 R_MeshQueue_RenderTransparent();
5191 if (r_timereport_active)
5192 R_TimeReport("drawtrans");
5194 R_SetupGenericShader(true);
5196 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))
5198 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5199 if (r_timereport_active)
5200 R_TimeReport("worlddebug");
5201 R_DrawModelsDebug();
5202 if (r_timereport_active)
5203 R_TimeReport("modeldebug");
5206 R_SetupGenericShader(true);
5208 if (cl.csqc_vidvars.drawworld)
5211 if (r_timereport_active)
5212 R_TimeReport("coronas");
5215 // don't let sound skip if going slow
5216 if (r_refdef.scene.extraupdate)
5219 R_ResetViewRendering2D();
5222 static const unsigned short bboxelements[36] =
5232 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5235 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5237 RSurf_ActiveWorldEntity();
5239 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5240 GL_DepthMask(false);
5241 GL_DepthRange(0, 1);
5242 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5243 R_Mesh_ResetTextureState();
5245 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5246 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5247 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5248 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5249 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5250 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5251 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5252 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5253 R_FillColors(color4f, 8, cr, cg, cb, ca);
5254 if (r_refdef.fogenabled)
5256 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5258 f1 = RSurf_FogVertex(v);
5260 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5261 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5262 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5265 R_Mesh_VertexPointer(vertex3f, 0, 0);
5266 R_Mesh_ColorPointer(color4f, 0, 0);
5267 R_Mesh_ResetTextureState();
5268 R_SetupGenericShader(false);
5269 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5272 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5276 prvm_edict_t *edict;
5277 prvm_prog_t *prog_save = prog;
5279 // this function draws bounding boxes of server entities
5283 GL_CullFace(GL_NONE);
5284 R_SetupGenericShader(false);
5288 for (i = 0;i < numsurfaces;i++)
5290 edict = PRVM_EDICT_NUM(surfacelist[i]);
5291 switch ((int)edict->fields.server->solid)
5293 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5294 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5295 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5296 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5297 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5298 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5300 color[3] *= r_showbboxes.value;
5301 color[3] = bound(0, color[3], 1);
5302 GL_DepthTest(!r_showdisabledepthtest.integer);
5303 GL_CullFace(r_refdef.view.cullface_front);
5304 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5310 static void R_DrawEntityBBoxes(void)
5313 prvm_edict_t *edict;
5315 prvm_prog_t *prog_save = prog;
5317 // this function draws bounding boxes of server entities
5323 for (i = 0;i < prog->num_edicts;i++)
5325 edict = PRVM_EDICT_NUM(i);
5326 if (edict->priv.server->free)
5328 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5329 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5331 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5333 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5334 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5340 static const int nomodelelement3i[24] =
5352 static const unsigned short nomodelelement3s[24] =
5364 static const float nomodelvertex3f[6*3] =
5374 static const float nomodelcolor4f[6*4] =
5376 0.0f, 0.0f, 0.5f, 1.0f,
5377 0.0f, 0.0f, 0.5f, 1.0f,
5378 0.0f, 0.5f, 0.0f, 1.0f,
5379 0.0f, 0.5f, 0.0f, 1.0f,
5380 0.5f, 0.0f, 0.0f, 1.0f,
5381 0.5f, 0.0f, 0.0f, 1.0f
5384 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5390 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);
5392 // this is only called once per entity so numsurfaces is always 1, and
5393 // surfacelist is always {0}, so this code does not handle batches
5395 if (rsurface.ent_flags & RENDER_ADDITIVE)
5397 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5398 GL_DepthMask(false);
5400 else if (rsurface.ent_color[3] < 1)
5402 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5403 GL_DepthMask(false);
5407 GL_BlendFunc(GL_ONE, GL_ZERO);
5410 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5411 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5412 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5413 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5414 R_SetupGenericShader(false);
5415 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5416 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5417 R_Mesh_ColorPointer(color4f, 0, 0);
5418 for (i = 0, c = color4f;i < 6;i++, c += 4)
5420 c[0] *= rsurface.ent_color[0];
5421 c[1] *= rsurface.ent_color[1];
5422 c[2] *= rsurface.ent_color[2];
5423 c[3] *= rsurface.ent_color[3];
5425 if (r_refdef.fogenabled)
5427 for (i = 0, c = color4f;i < 6;i++, c += 4)
5429 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5431 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5432 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5433 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5436 R_Mesh_ResetTextureState();
5437 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5440 void R_DrawNoModel(entity_render_t *ent)
5443 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5444 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5445 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5447 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5450 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5452 vec3_t right1, right2, diff, normal;
5454 VectorSubtract (org2, org1, normal);
5456 // calculate 'right' vector for start
5457 VectorSubtract (r_refdef.view.origin, org1, diff);
5458 CrossProduct (normal, diff, right1);
5459 VectorNormalize (right1);
5461 // calculate 'right' vector for end
5462 VectorSubtract (r_refdef.view.origin, org2, diff);
5463 CrossProduct (normal, diff, right2);
5464 VectorNormalize (right2);
5466 vert[ 0] = org1[0] + width * right1[0];
5467 vert[ 1] = org1[1] + width * right1[1];
5468 vert[ 2] = org1[2] + width * right1[2];
5469 vert[ 3] = org1[0] - width * right1[0];
5470 vert[ 4] = org1[1] - width * right1[1];
5471 vert[ 5] = org1[2] - width * right1[2];
5472 vert[ 6] = org2[0] - width * right2[0];
5473 vert[ 7] = org2[1] - width * right2[1];
5474 vert[ 8] = org2[2] - width * right2[2];
5475 vert[ 9] = org2[0] + width * right2[0];
5476 vert[10] = org2[1] + width * right2[1];
5477 vert[11] = org2[2] + width * right2[2];
5480 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)
5482 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5483 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5484 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5485 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5486 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5487 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5488 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5489 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5490 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5491 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5492 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5493 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5496 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5501 VectorSet(v, x, y, z);
5502 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5503 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5505 if (i == mesh->numvertices)
5507 if (mesh->numvertices < mesh->maxvertices)
5509 VectorCopy(v, vertex3f);
5510 mesh->numvertices++;
5512 return mesh->numvertices;
5518 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5522 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5523 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5524 e = mesh->element3i + mesh->numtriangles * 3;
5525 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5527 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5528 if (mesh->numtriangles < mesh->maxtriangles)
5533 mesh->numtriangles++;
5535 element[1] = element[2];
5539 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5543 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5544 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5545 e = mesh->element3i + mesh->numtriangles * 3;
5546 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5548 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5549 if (mesh->numtriangles < mesh->maxtriangles)
5554 mesh->numtriangles++;
5556 element[1] = element[2];
5560 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5561 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5563 int planenum, planenum2;
5566 mplane_t *plane, *plane2;
5568 double temppoints[2][256*3];
5569 // figure out how large a bounding box we need to properly compute this brush
5571 for (w = 0;w < numplanes;w++)
5572 maxdist = max(maxdist, fabs(planes[w].dist));
5573 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5574 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5575 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5579 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5580 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5582 if (planenum2 == planenum)
5584 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);
5587 if (tempnumpoints < 3)
5589 // generate elements forming a triangle fan for this polygon
5590 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5594 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)
5596 texturelayer_t *layer;
5597 layer = t->currentlayers + t->currentnumlayers++;
5599 layer->depthmask = depthmask;
5600 layer->blendfunc1 = blendfunc1;
5601 layer->blendfunc2 = blendfunc2;
5602 layer->texture = texture;
5603 layer->texmatrix = *matrix;
5604 layer->color[0] = r * r_refdef.view.colorscale;
5605 layer->color[1] = g * r_refdef.view.colorscale;
5606 layer->color[2] = b * r_refdef.view.colorscale;
5607 layer->color[3] = a;
5610 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5613 index = parms[2] + r_refdef.scene.time * parms[3];
5614 index -= floor(index);
5618 case Q3WAVEFUNC_NONE:
5619 case Q3WAVEFUNC_NOISE:
5620 case Q3WAVEFUNC_COUNT:
5623 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5624 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5625 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5626 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5627 case Q3WAVEFUNC_TRIANGLE:
5629 f = index - floor(index);
5640 return (float)(parms[0] + parms[1] * f);
5643 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5648 matrix4x4_t matrix, temp;
5649 switch(tcmod->tcmod)
5653 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5654 matrix = r_waterscrollmatrix;
5656 matrix = identitymatrix;
5658 case Q3TCMOD_ENTITYTRANSLATE:
5659 // this is used in Q3 to allow the gamecode to control texcoord
5660 // scrolling on the entity, which is not supported in darkplaces yet.
5661 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5663 case Q3TCMOD_ROTATE:
5664 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5665 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5666 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5669 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5671 case Q3TCMOD_SCROLL:
5672 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5674 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5675 w = (int) tcmod->parms[0];
5676 h = (int) tcmod->parms[1];
5677 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5679 idx = (int) floor(f * w * h);
5680 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5682 case Q3TCMOD_STRETCH:
5683 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5684 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5686 case Q3TCMOD_TRANSFORM:
5687 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5688 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5689 VectorSet(tcmat + 6, 0 , 0 , 1);
5690 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5691 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5693 case Q3TCMOD_TURBULENT:
5694 // this is handled in the RSurf_PrepareVertices function
5695 matrix = identitymatrix;
5699 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5702 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5704 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5705 char name[MAX_QPATH];
5706 skinframe_t *skinframe;
5707 unsigned char pixels[296*194];
5708 strlcpy(cache->name, skinname, sizeof(cache->name));
5709 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5710 if (developer_loading.integer)
5711 Con_Printf("loading %s\n", name);
5712 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5713 if (!skinframe || !skinframe->base)
5716 fs_offset_t filesize;
5718 f = FS_LoadFile(name, tempmempool, true, &filesize);
5721 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5722 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5726 cache->skinframe = skinframe;
5729 texture_t *R_GetCurrentTexture(texture_t *t)
5732 const entity_render_t *ent = rsurface.entity;
5733 dp_model_t *model = ent->model;
5734 q3shaderinfo_layer_tcmod_t *tcmod;
5736 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5737 return t->currentframe;
5738 t->update_lastrenderframe = r_frame;
5739 t->update_lastrenderentity = (void *)ent;
5741 // switch to an alternate material if this is a q1bsp animated material
5743 texture_t *texture = t;
5744 int s = rsurface.ent_skinnum;
5745 if ((unsigned int)s >= (unsigned int)model->numskins)
5747 if (model->skinscenes)
5749 if (model->skinscenes[s].framecount > 1)
5750 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5752 s = model->skinscenes[s].firstframe;
5755 t = t + s * model->num_surfaces;
5758 // use an alternate animation if the entity's frame is not 0,
5759 // and only if the texture has an alternate animation
5760 if (rsurface.ent_alttextures && t->anim_total[1])
5761 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5763 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5765 texture->currentframe = t;
5768 // update currentskinframe to be a qw skin or animation frame
5769 if (rsurface.ent_qwskin >= 0)
5771 i = rsurface.ent_qwskin;
5772 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5774 r_qwskincache_size = cl.maxclients;
5776 Mem_Free(r_qwskincache);
5777 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5779 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5780 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5781 t->currentskinframe = r_qwskincache[i].skinframe;
5782 if (t->currentskinframe == NULL)
5783 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5785 else if (t->numskinframes >= 2)
5786 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5787 if (t->backgroundnumskinframes >= 2)
5788 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5790 t->currentmaterialflags = t->basematerialflags;
5791 t->currentalpha = rsurface.ent_color[3];
5792 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5793 t->currentalpha *= r_wateralpha.value;
5794 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5795 t->currentalpha *= t->r_water_wateralpha;
5796 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5797 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5798 if (!(rsurface.ent_flags & RENDER_LIGHT))
5799 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5800 else if (rsurface.modeltexcoordlightmap2f == NULL)
5802 // pick a model lighting mode
5803 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5804 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5806 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5808 if (rsurface.ent_flags & RENDER_ADDITIVE)
5809 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5810 else if (t->currentalpha < 1)
5811 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5812 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5813 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5814 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5815 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5816 if (t->backgroundnumskinframes)
5817 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5818 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5820 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5821 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5824 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5826 // there is no tcmod
5827 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5829 t->currenttexmatrix = r_waterscrollmatrix;
5830 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5832 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
5834 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5835 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5838 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5839 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5840 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5841 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5843 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5844 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5845 t->glosstexture = r_texture_black;
5846 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5847 t->backgroundglosstexture = r_texture_black;
5848 t->specularpower = r_shadow_glossexponent.value;
5849 // TODO: store reference values for these in the texture?
5850 t->specularscale = 0;
5851 if (r_shadow_gloss.integer > 0)
5853 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5855 if (r_shadow_glossintensity.value > 0)
5857 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5858 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5859 t->specularscale = r_shadow_glossintensity.value;
5862 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5864 t->glosstexture = r_texture_white;
5865 t->backgroundglosstexture = r_texture_white;
5866 t->specularscale = r_shadow_gloss2intensity.value;
5867 t->specularpower = r_shadow_gloss2exponent.value;
5870 t->specularscale *= t->specularscalemod;
5871 t->specularpower *= t->specularpowermod;
5873 // lightmaps mode looks bad with dlights using actual texturing, so turn
5874 // off the colormap and glossmap, but leave the normalmap on as it still
5875 // accurately represents the shading involved
5876 if (gl_lightmaps.integer)
5878 t->basetexture = r_texture_grey128;
5879 t->backgroundbasetexture = NULL;
5880 t->specularscale = 0;
5881 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5884 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5885 VectorClear(t->dlightcolor);
5886 t->currentnumlayers = 0;
5887 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5890 int blendfunc1, blendfunc2;
5892 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5894 blendfunc1 = GL_SRC_ALPHA;
5895 blendfunc2 = GL_ONE;
5897 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5899 blendfunc1 = GL_SRC_ALPHA;
5900 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5902 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5904 blendfunc1 = t->customblendfunc[0];
5905 blendfunc2 = t->customblendfunc[1];
5909 blendfunc1 = GL_ONE;
5910 blendfunc2 = GL_ZERO;
5912 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5913 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5914 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5915 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5917 // fullbright is not affected by r_refdef.lightmapintensity
5918 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]);
5919 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5920 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]);
5921 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5922 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]);
5926 vec3_t ambientcolor;
5928 // set the color tint used for lights affecting this surface
5929 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5931 // q3bsp has no lightmap updates, so the lightstylevalue that
5932 // would normally be baked into the lightmap must be
5933 // applied to the color
5934 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5935 if (model->type == mod_brushq3)
5936 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5937 colorscale *= r_refdef.lightmapintensity;
5938 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5939 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5940 // basic lit geometry
5941 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]);
5942 // add pants/shirt if needed
5943 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5944 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_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]);
5945 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5946 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_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]);
5947 // now add ambient passes if needed
5948 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5950 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]);
5951 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5952 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]);
5953 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5954 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]);
5957 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5958 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]);
5959 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5961 // if this is opaque use alpha blend which will darken the earlier
5964 // if this is an alpha blended material, all the earlier passes
5965 // were darkened by fog already, so we only need to add the fog
5966 // color ontop through the fog mask texture
5968 // if this is an additive blended material, all the earlier passes
5969 // were darkened by fog already, and we should not add fog color
5970 // (because the background was not darkened, there is no fog color
5971 // that was lost behind it).
5972 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]);
5976 return t->currentframe;
5979 rsurfacestate_t rsurface;
5981 void R_Mesh_ResizeArrays(int newvertices)
5984 if (rsurface.array_size >= newvertices)
5986 if (rsurface.array_modelvertex3f)
5987 Mem_Free(rsurface.array_modelvertex3f);
5988 rsurface.array_size = (newvertices + 1023) & ~1023;
5989 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5990 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5991 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5992 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5993 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5994 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5995 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5996 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5997 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5998 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5999 rsurface.array_color4f = base + rsurface.array_size * 27;
6000 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6003 void RSurf_ActiveWorldEntity(void)
6005 dp_model_t *model = r_refdef.scene.worldmodel;
6006 //if (rsurface.entity == r_refdef.scene.worldentity)
6008 rsurface.entity = r_refdef.scene.worldentity;
6009 rsurface.ent_skinnum = 0;
6010 rsurface.ent_qwskin = -1;
6011 rsurface.ent_shadertime = 0;
6012 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
6013 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6014 if (rsurface.array_size < model->surfmesh.num_vertices)
6015 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6016 rsurface.matrix = identitymatrix;
6017 rsurface.inversematrix = identitymatrix;
6018 rsurface.matrixscale = 1;
6019 rsurface.inversematrixscale = 1;
6020 R_Mesh_Matrix(&identitymatrix);
6021 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6022 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6023 rsurface.fograngerecip = r_refdef.fograngerecip;
6024 rsurface.fogheightfade = r_refdef.fogheightfade;
6025 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6026 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6027 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6028 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6029 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6030 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6031 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6032 VectorSet(rsurface.glowmod, 1, 1, 1);
6033 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6034 rsurface.frameblend[0].lerp = 1;
6035 rsurface.ent_alttextures = false;
6036 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6037 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6038 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6039 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6040 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6041 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6042 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6043 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6044 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6045 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6046 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6047 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6048 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6049 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6050 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6051 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6052 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6053 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6054 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6055 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6056 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6057 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6058 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6059 rsurface.modelelement3i = model->surfmesh.data_element3i;
6060 rsurface.modelelement3s = model->surfmesh.data_element3s;
6061 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6062 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6063 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6064 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6065 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6066 rsurface.modelsurfaces = model->data_surfaces;
6067 rsurface.generatedvertex = false;
6068 rsurface.vertex3f = rsurface.modelvertex3f;
6069 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6070 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6071 rsurface.svector3f = rsurface.modelsvector3f;
6072 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6073 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6074 rsurface.tvector3f = rsurface.modeltvector3f;
6075 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6076 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6077 rsurface.normal3f = rsurface.modelnormal3f;
6078 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6079 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6080 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6083 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6085 dp_model_t *model = ent->model;
6086 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6088 rsurface.entity = (entity_render_t *)ent;
6089 rsurface.ent_skinnum = ent->skinnum;
6090 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;
6091 rsurface.ent_shadertime = ent->shadertime;
6092 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6093 rsurface.ent_flags = ent->flags;
6094 if (rsurface.array_size < model->surfmesh.num_vertices)
6095 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6096 rsurface.matrix = ent->matrix;
6097 rsurface.inversematrix = ent->inversematrix;
6098 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6099 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6100 R_Mesh_Matrix(&rsurface.matrix);
6101 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6102 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6103 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6104 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6105 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6106 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6107 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6108 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6109 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6110 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6111 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6112 VectorCopy(ent->glowmod, rsurface.glowmod);
6113 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6114 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6115 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6116 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6117 if (ent->model->brush.submodel)
6119 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6120 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6122 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6124 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6126 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6127 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6128 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6129 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6131 else if (wanttangents)
6133 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6134 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6135 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6136 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6137 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6139 else if (wantnormals)
6141 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6142 rsurface.modelsvector3f = NULL;
6143 rsurface.modeltvector3f = NULL;
6144 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6145 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6149 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6150 rsurface.modelsvector3f = NULL;
6151 rsurface.modeltvector3f = NULL;
6152 rsurface.modelnormal3f = NULL;
6153 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6155 rsurface.modelvertex3f_bufferobject = 0;
6156 rsurface.modelvertex3f_bufferoffset = 0;
6157 rsurface.modelsvector3f_bufferobject = 0;
6158 rsurface.modelsvector3f_bufferoffset = 0;
6159 rsurface.modeltvector3f_bufferobject = 0;
6160 rsurface.modeltvector3f_bufferoffset = 0;
6161 rsurface.modelnormal3f_bufferobject = 0;
6162 rsurface.modelnormal3f_bufferoffset = 0;
6163 rsurface.generatedvertex = true;
6167 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6168 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6169 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6170 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6171 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6172 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6173 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6174 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6175 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6176 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6177 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6178 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6179 rsurface.generatedvertex = false;
6181 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6182 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6183 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6184 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6185 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6186 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6187 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6188 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6189 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6190 rsurface.modelelement3i = model->surfmesh.data_element3i;
6191 rsurface.modelelement3s = model->surfmesh.data_element3s;
6192 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6193 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6194 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6195 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6196 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6197 rsurface.modelsurfaces = model->data_surfaces;
6198 rsurface.vertex3f = rsurface.modelvertex3f;
6199 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6200 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6201 rsurface.svector3f = rsurface.modelsvector3f;
6202 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6203 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6204 rsurface.tvector3f = rsurface.modeltvector3f;
6205 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6206 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6207 rsurface.normal3f = rsurface.modelnormal3f;
6208 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6209 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6210 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6213 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)
6215 rsurface.entity = r_refdef.scene.worldentity;
6216 rsurface.ent_skinnum = 0;
6217 rsurface.ent_qwskin = -1;
6218 rsurface.ent_shadertime = shadertime;
6219 Vector4Set(rsurface.ent_color, r, g, b, a);
6220 rsurface.ent_flags = entflags;
6221 rsurface.modelnum_vertices = numvertices;
6222 rsurface.modelnum_triangles = numtriangles;
6223 if (rsurface.array_size < rsurface.modelnum_vertices)
6224 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6225 rsurface.matrix = *matrix;
6226 rsurface.inversematrix = *inversematrix;
6227 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6228 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6229 R_Mesh_Matrix(&rsurface.matrix);
6230 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6231 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6232 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6233 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6234 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6235 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6236 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6237 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6238 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6239 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6240 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6241 VectorSet(rsurface.glowmod, 1, 1, 1);
6242 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6243 rsurface.frameblend[0].lerp = 1;
6244 rsurface.ent_alttextures = false;
6245 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6246 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6249 rsurface.modelvertex3f = vertex3f;
6250 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6251 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6252 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6254 else if (wantnormals)
6256 rsurface.modelvertex3f = vertex3f;
6257 rsurface.modelsvector3f = NULL;
6258 rsurface.modeltvector3f = NULL;
6259 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6263 rsurface.modelvertex3f = vertex3f;
6264 rsurface.modelsvector3f = NULL;
6265 rsurface.modeltvector3f = NULL;
6266 rsurface.modelnormal3f = NULL;
6268 rsurface.modelvertex3f_bufferobject = 0;
6269 rsurface.modelvertex3f_bufferoffset = 0;
6270 rsurface.modelsvector3f_bufferobject = 0;
6271 rsurface.modelsvector3f_bufferoffset = 0;
6272 rsurface.modeltvector3f_bufferobject = 0;
6273 rsurface.modeltvector3f_bufferoffset = 0;
6274 rsurface.modelnormal3f_bufferobject = 0;
6275 rsurface.modelnormal3f_bufferoffset = 0;
6276 rsurface.generatedvertex = true;
6277 rsurface.modellightmapcolor4f = color4f;
6278 rsurface.modellightmapcolor4f_bufferobject = 0;
6279 rsurface.modellightmapcolor4f_bufferoffset = 0;
6280 rsurface.modeltexcoordtexture2f = texcoord2f;
6281 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6282 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6283 rsurface.modeltexcoordlightmap2f = NULL;
6284 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6285 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6286 rsurface.modelelement3i = element3i;
6287 rsurface.modelelement3s = element3s;
6288 rsurface.modelelement3i_bufferobject = 0;
6289 rsurface.modelelement3s_bufferobject = 0;
6290 rsurface.modellightmapoffsets = NULL;
6291 rsurface.modelsurfaces = NULL;
6292 rsurface.vertex3f = rsurface.modelvertex3f;
6293 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6294 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6295 rsurface.svector3f = rsurface.modelsvector3f;
6296 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6297 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6298 rsurface.tvector3f = rsurface.modeltvector3f;
6299 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6300 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6301 rsurface.normal3f = rsurface.modelnormal3f;
6302 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6303 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6304 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6306 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6308 if ((wantnormals || wanttangents) && !normal3f)
6309 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6310 if (wanttangents && !svector3f)
6311 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);
6315 float RSurf_FogPoint(const float *v)
6317 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6318 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6319 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6320 float FogHeightFade = r_refdef.fogheightfade;
6322 unsigned int fogmasktableindex;
6323 if (r_refdef.fogplaneviewabove)
6324 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6326 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6327 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6328 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6331 float RSurf_FogVertex(const float *v)
6333 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6334 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6335 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6336 float FogHeightFade = rsurface.fogheightfade;
6338 unsigned int fogmasktableindex;
6339 if (r_refdef.fogplaneviewabove)
6340 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6342 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6343 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6344 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6347 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6348 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6351 int texturesurfaceindex;
6356 const float *v1, *in_tc;
6358 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6360 q3shaderinfo_deform_t *deform;
6361 // 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
6362 if (rsurface.generatedvertex)
6364 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6365 generatenormals = true;
6366 for (i = 0;i < Q3MAXDEFORMS;i++)
6368 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6370 generatetangents = true;
6371 generatenormals = true;
6373 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6374 generatenormals = true;
6376 if (generatenormals && !rsurface.modelnormal3f)
6378 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6379 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6380 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6381 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6383 if (generatetangents && !rsurface.modelsvector3f)
6385 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6386 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6387 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6388 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6389 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6390 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6391 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);
6394 rsurface.vertex3f = rsurface.modelvertex3f;
6395 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6396 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6397 rsurface.svector3f = rsurface.modelsvector3f;
6398 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6399 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6400 rsurface.tvector3f = rsurface.modeltvector3f;
6401 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6402 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6403 rsurface.normal3f = rsurface.modelnormal3f;
6404 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6405 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6406 // if vertices are deformed (sprite flares and things in maps, possibly
6407 // water waves, bulges and other deformations), generate them into
6408 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6409 // (may be static model data or generated data for an animated model, or
6410 // the previous deform pass)
6411 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6413 switch (deform->deform)
6416 case Q3DEFORM_PROJECTIONSHADOW:
6417 case Q3DEFORM_TEXT0:
6418 case Q3DEFORM_TEXT1:
6419 case Q3DEFORM_TEXT2:
6420 case Q3DEFORM_TEXT3:
6421 case Q3DEFORM_TEXT4:
6422 case Q3DEFORM_TEXT5:
6423 case Q3DEFORM_TEXT6:
6424 case Q3DEFORM_TEXT7:
6427 case Q3DEFORM_AUTOSPRITE:
6428 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6429 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6430 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6431 VectorNormalize(newforward);
6432 VectorNormalize(newright);
6433 VectorNormalize(newup);
6434 // make deformed versions of only the model vertices used by the specified surfaces
6435 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6437 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6438 // a single autosprite surface can contain multiple sprites...
6439 for (j = 0;j < surface->num_vertices - 3;j += 4)
6441 VectorClear(center);
6442 for (i = 0;i < 4;i++)
6443 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6444 VectorScale(center, 0.25f, center);
6445 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6446 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6447 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6448 for (i = 0;i < 4;i++)
6450 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6451 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6454 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);
6455 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);
6457 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6458 rsurface.vertex3f_bufferobject = 0;
6459 rsurface.vertex3f_bufferoffset = 0;
6460 rsurface.svector3f = rsurface.array_deformedsvector3f;
6461 rsurface.svector3f_bufferobject = 0;
6462 rsurface.svector3f_bufferoffset = 0;
6463 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6464 rsurface.tvector3f_bufferobject = 0;
6465 rsurface.tvector3f_bufferoffset = 0;
6466 rsurface.normal3f = rsurface.array_deformednormal3f;
6467 rsurface.normal3f_bufferobject = 0;
6468 rsurface.normal3f_bufferoffset = 0;
6470 case Q3DEFORM_AUTOSPRITE2:
6471 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6472 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6473 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6474 VectorNormalize(newforward);
6475 VectorNormalize(newright);
6476 VectorNormalize(newup);
6477 // make deformed versions of only the model vertices used by the specified surfaces
6478 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6480 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6481 const float *v1, *v2;
6491 memset(shortest, 0, sizeof(shortest));
6492 // a single autosprite surface can contain multiple sprites...
6493 for (j = 0;j < surface->num_vertices - 3;j += 4)
6495 VectorClear(center);
6496 for (i = 0;i < 4;i++)
6497 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6498 VectorScale(center, 0.25f, center);
6499 // find the two shortest edges, then use them to define the
6500 // axis vectors for rotating around the central axis
6501 for (i = 0;i < 6;i++)
6503 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6504 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6506 Debug_PolygonBegin(NULL, 0);
6507 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6508 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);
6509 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6512 l = VectorDistance2(v1, v2);
6513 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6515 l += (1.0f / 1024.0f);
6516 if (shortest[0].length2 > l || i == 0)
6518 shortest[1] = shortest[0];
6519 shortest[0].length2 = l;
6520 shortest[0].v1 = v1;
6521 shortest[0].v2 = v2;
6523 else if (shortest[1].length2 > l || i == 1)
6525 shortest[1].length2 = l;
6526 shortest[1].v1 = v1;
6527 shortest[1].v2 = v2;
6530 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6531 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6533 Debug_PolygonBegin(NULL, 0);
6534 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6535 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);
6536 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6539 // this calculates the right vector from the shortest edge
6540 // and the up vector from the edge midpoints
6541 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6542 VectorNormalize(right);
6543 VectorSubtract(end, start, up);
6544 VectorNormalize(up);
6545 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6546 VectorSubtract(rsurface.localvieworigin, center, forward);
6547 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6548 VectorNegate(forward, forward);
6549 VectorReflect(forward, 0, up, forward);
6550 VectorNormalize(forward);
6551 CrossProduct(up, forward, newright);
6552 VectorNormalize(newright);
6554 Debug_PolygonBegin(NULL, 0);
6555 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);
6556 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6557 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6561 Debug_PolygonBegin(NULL, 0);
6562 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6563 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6564 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6567 // rotate the quad around the up axis vector, this is made
6568 // especially easy by the fact we know the quad is flat,
6569 // so we only have to subtract the center position and
6570 // measure distance along the right vector, and then
6571 // multiply that by the newright vector and add back the
6573 // we also need to subtract the old position to undo the
6574 // displacement from the center, which we do with a
6575 // DotProduct, the subtraction/addition of center is also
6576 // optimized into DotProducts here
6577 l = DotProduct(right, center);
6578 for (i = 0;i < 4;i++)
6580 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6581 f = DotProduct(right, v1) - l;
6582 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6585 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);
6586 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);
6588 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6589 rsurface.vertex3f_bufferobject = 0;
6590 rsurface.vertex3f_bufferoffset = 0;
6591 rsurface.svector3f = rsurface.array_deformedsvector3f;
6592 rsurface.svector3f_bufferobject = 0;
6593 rsurface.svector3f_bufferoffset = 0;
6594 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6595 rsurface.tvector3f_bufferobject = 0;
6596 rsurface.tvector3f_bufferoffset = 0;
6597 rsurface.normal3f = rsurface.array_deformednormal3f;
6598 rsurface.normal3f_bufferobject = 0;
6599 rsurface.normal3f_bufferoffset = 0;
6601 case Q3DEFORM_NORMAL:
6602 // deform the normals to make reflections wavey
6603 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6605 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6606 for (j = 0;j < surface->num_vertices;j++)
6609 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6610 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6611 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6612 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6613 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6614 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6615 VectorNormalize(normal);
6617 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);
6619 rsurface.svector3f = rsurface.array_deformedsvector3f;
6620 rsurface.svector3f_bufferobject = 0;
6621 rsurface.svector3f_bufferoffset = 0;
6622 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6623 rsurface.tvector3f_bufferobject = 0;
6624 rsurface.tvector3f_bufferoffset = 0;
6625 rsurface.normal3f = rsurface.array_deformednormal3f;
6626 rsurface.normal3f_bufferobject = 0;
6627 rsurface.normal3f_bufferoffset = 0;
6630 // deform vertex array to make wavey water and flags and such
6631 waveparms[0] = deform->waveparms[0];
6632 waveparms[1] = deform->waveparms[1];
6633 waveparms[2] = deform->waveparms[2];
6634 waveparms[3] = deform->waveparms[3];
6635 // this is how a divisor of vertex influence on deformation
6636 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6637 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6638 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6640 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6641 for (j = 0;j < surface->num_vertices;j++)
6643 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6644 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6645 // if the wavefunc depends on time, evaluate it per-vertex
6648 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6649 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6651 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6654 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6655 rsurface.vertex3f_bufferobject = 0;
6656 rsurface.vertex3f_bufferoffset = 0;
6658 case Q3DEFORM_BULGE:
6659 // deform vertex array to make the surface have moving bulges
6660 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6662 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6663 for (j = 0;j < surface->num_vertices;j++)
6665 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6666 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6669 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6670 rsurface.vertex3f_bufferobject = 0;
6671 rsurface.vertex3f_bufferoffset = 0;
6674 // deform vertex array
6675 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6676 VectorScale(deform->parms, scale, waveparms);
6677 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6679 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6680 for (j = 0;j < surface->num_vertices;j++)
6681 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6683 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6684 rsurface.vertex3f_bufferobject = 0;
6685 rsurface.vertex3f_bufferoffset = 0;
6689 // generate texcoords based on the chosen texcoord source
6690 switch(rsurface.texture->tcgen.tcgen)
6693 case Q3TCGEN_TEXTURE:
6694 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6695 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6696 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6698 case Q3TCGEN_LIGHTMAP:
6699 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6700 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6701 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6703 case Q3TCGEN_VECTOR:
6704 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6706 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6707 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)
6709 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6710 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6713 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6714 rsurface.texcoordtexture2f_bufferobject = 0;
6715 rsurface.texcoordtexture2f_bufferoffset = 0;
6717 case Q3TCGEN_ENVIRONMENT:
6718 // make environment reflections using a spheremap
6719 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6721 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6722 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6723 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6724 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6725 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6727 // identical to Q3A's method, but executed in worldspace so
6728 // carried models can be shiny too
6730 float viewer[3], d, reflected[3], worldreflected[3];
6732 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6733 // VectorNormalize(viewer);
6735 d = DotProduct(normal, viewer);
6737 reflected[0] = normal[0]*2*d - viewer[0];
6738 reflected[1] = normal[1]*2*d - viewer[1];
6739 reflected[2] = normal[2]*2*d - viewer[2];
6740 // note: this is proportinal to viewer, so we can normalize later
6742 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6743 VectorNormalize(worldreflected);
6745 // note: this sphere map only uses world x and z!
6746 // so positive and negative y will LOOK THE SAME.
6747 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6748 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6751 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6752 rsurface.texcoordtexture2f_bufferobject = 0;
6753 rsurface.texcoordtexture2f_bufferoffset = 0;
6756 // the only tcmod that needs software vertex processing is turbulent, so
6757 // check for it here and apply the changes if needed
6758 // and we only support that as the first one
6759 // (handling a mixture of turbulent and other tcmods would be problematic
6760 // without punting it entirely to a software path)
6761 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6763 amplitude = rsurface.texture->tcmods[0].parms[1];
6764 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6765 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6767 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6768 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)
6770 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6771 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6774 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6775 rsurface.texcoordtexture2f_bufferobject = 0;
6776 rsurface.texcoordtexture2f_bufferoffset = 0;
6778 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6779 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6780 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6781 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6784 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6787 const msurface_t *surface = texturesurfacelist[0];
6788 const msurface_t *surface2;
6793 // TODO: lock all array ranges before render, rather than on each surface
6794 if (texturenumsurfaces == 1)
6796 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6797 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);
6799 else if (r_batchmode.integer == 2)
6801 #define MAXBATCHTRIANGLES 4096
6802 int batchtriangles = 0;
6803 int batchelements[MAXBATCHTRIANGLES*3];
6804 for (i = 0;i < texturenumsurfaces;i = j)
6806 surface = texturesurfacelist[i];
6808 if (surface->num_triangles > MAXBATCHTRIANGLES)
6810 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);
6813 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6814 batchtriangles = surface->num_triangles;
6815 firstvertex = surface->num_firstvertex;
6816 endvertex = surface->num_firstvertex + surface->num_vertices;
6817 for (;j < texturenumsurfaces;j++)
6819 surface2 = texturesurfacelist[j];
6820 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6822 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6823 batchtriangles += surface2->num_triangles;
6824 firstvertex = min(firstvertex, surface2->num_firstvertex);
6825 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6827 surface2 = texturesurfacelist[j-1];
6828 numvertices = endvertex - firstvertex;
6829 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6832 else if (r_batchmode.integer == 1)
6834 for (i = 0;i < texturenumsurfaces;i = j)
6836 surface = texturesurfacelist[i];
6837 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6838 if (texturesurfacelist[j] != surface2)
6840 surface2 = texturesurfacelist[j-1];
6841 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6842 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6843 GL_LockArrays(surface->num_firstvertex, numvertices);
6844 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6849 for (i = 0;i < texturenumsurfaces;i++)
6851 surface = texturesurfacelist[i];
6852 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6853 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);
6858 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6860 int i, planeindex, vertexindex;
6864 r_waterstate_waterplane_t *p, *bestp;
6865 const msurface_t *surface;
6866 if (r_waterstate.renderingscene)
6868 for (i = 0;i < texturenumsurfaces;i++)
6870 surface = texturesurfacelist[i];
6871 if (lightmaptexunit >= 0)
6872 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6873 if (deluxemaptexunit >= 0)
6874 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6875 // pick the closest matching water plane
6878 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6881 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6883 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6884 d += fabs(PlaneDiff(vert, &p->plane));
6886 if (bestd > d || !bestp)
6894 if (refractiontexunit >= 0)
6895 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6896 if (reflectiontexunit >= 0)
6897 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6901 if (refractiontexunit >= 0)
6902 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6903 if (reflectiontexunit >= 0)
6904 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6906 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6907 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);
6911 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6915 const msurface_t *surface = texturesurfacelist[0];
6916 const msurface_t *surface2;
6921 // TODO: lock all array ranges before render, rather than on each surface
6922 if (texturenumsurfaces == 1)
6924 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6925 if (deluxemaptexunit >= 0)
6926 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
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);
6930 else if (r_batchmode.integer == 2)
6932 #define MAXBATCHTRIANGLES 4096
6933 int batchtriangles = 0;
6934 int batchelements[MAXBATCHTRIANGLES*3];
6935 for (i = 0;i < texturenumsurfaces;i = j)
6937 surface = texturesurfacelist[i];
6938 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6939 if (deluxemaptexunit >= 0)
6940 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6942 if (surface->num_triangles > MAXBATCHTRIANGLES)
6944 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);
6947 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6948 batchtriangles = surface->num_triangles;
6949 firstvertex = surface->num_firstvertex;
6950 endvertex = surface->num_firstvertex + surface->num_vertices;
6951 for (;j < texturenumsurfaces;j++)
6953 surface2 = texturesurfacelist[j];
6954 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6956 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6957 batchtriangles += surface2->num_triangles;
6958 firstvertex = min(firstvertex, surface2->num_firstvertex);
6959 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6961 surface2 = texturesurfacelist[j-1];
6962 numvertices = endvertex - firstvertex;
6963 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6966 else if (r_batchmode.integer == 1)
6969 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6970 for (i = 0;i < texturenumsurfaces;i = j)
6972 surface = texturesurfacelist[i];
6973 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6974 if (texturesurfacelist[j] != surface2)
6976 Con_Printf(" %i", j - i);
6979 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6981 for (i = 0;i < texturenumsurfaces;i = j)
6983 surface = texturesurfacelist[i];
6984 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6985 if (deluxemaptexunit >= 0)
6986 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6987 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6988 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6991 Con_Printf(" %i", j - i);
6993 surface2 = texturesurfacelist[j-1];
6994 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6995 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6996 GL_LockArrays(surface->num_firstvertex, numvertices);
6997 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7005 for (i = 0;i < texturenumsurfaces;i++)
7007 surface = texturesurfacelist[i];
7008 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7009 if (deluxemaptexunit >= 0)
7010 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7011 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7012 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);
7017 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7020 int texturesurfaceindex;
7021 if (r_showsurfaces.integer == 2)
7023 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7025 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7026 for (j = 0;j < surface->num_triangles;j++)
7028 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7029 GL_Color(f, f, f, 1);
7030 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7036 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7038 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7039 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7040 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);
7041 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7042 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);
7047 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7049 int texturesurfaceindex;
7053 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7055 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7056 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)
7064 rsurface.lightmapcolor4f = rsurface.array_color4f;
7065 rsurface.lightmapcolor4f_bufferobject = 0;
7066 rsurface.lightmapcolor4f_bufferoffset = 0;
7069 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7071 int texturesurfaceindex;
7077 if (rsurface.lightmapcolor4f)
7079 // generate color arrays for the surfaces in this list
7080 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7082 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7083 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), 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)
7085 f = RSurf_FogVertex(v);
7095 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7097 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7098 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)
7100 f = RSurf_FogVertex(v);
7108 rsurface.lightmapcolor4f = rsurface.array_color4f;
7109 rsurface.lightmapcolor4f_bufferobject = 0;
7110 rsurface.lightmapcolor4f_bufferoffset = 0;
7113 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7115 int texturesurfaceindex;
7121 if (!rsurface.lightmapcolor4f)
7123 // generate color arrays for the surfaces in this list
7124 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7126 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7127 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)
7129 f = RSurf_FogVertex(v);
7130 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7131 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7132 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7136 rsurface.lightmapcolor4f = rsurface.array_color4f;
7137 rsurface.lightmapcolor4f_bufferobject = 0;
7138 rsurface.lightmapcolor4f_bufferoffset = 0;
7141 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7143 int texturesurfaceindex;
7147 if (!rsurface.lightmapcolor4f)
7149 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7151 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7152 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)
7160 rsurface.lightmapcolor4f = rsurface.array_color4f;
7161 rsurface.lightmapcolor4f_bufferobject = 0;
7162 rsurface.lightmapcolor4f_bufferoffset = 0;
7165 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7167 int texturesurfaceindex;
7171 if (!rsurface.lightmapcolor4f)
7173 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7175 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7176 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)
7178 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7179 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7180 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7184 rsurface.lightmapcolor4f = rsurface.array_color4f;
7185 rsurface.lightmapcolor4f_bufferobject = 0;
7186 rsurface.lightmapcolor4f_bufferoffset = 0;
7189 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7192 rsurface.lightmapcolor4f = NULL;
7193 rsurface.lightmapcolor4f_bufferobject = 0;
7194 rsurface.lightmapcolor4f_bufferoffset = 0;
7195 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7196 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7197 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7198 GL_Color(r, g, b, a);
7199 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7202 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7204 // TODO: optimize applyfog && applycolor case
7205 // just apply fog if necessary, and tint the fog color array if necessary
7206 rsurface.lightmapcolor4f = NULL;
7207 rsurface.lightmapcolor4f_bufferobject = 0;
7208 rsurface.lightmapcolor4f_bufferoffset = 0;
7209 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7210 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7211 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7212 GL_Color(r, g, b, a);
7213 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7216 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7218 int texturesurfaceindex;
7222 if (texturesurfacelist[0]->lightmapinfo)
7224 // generate color arrays for the surfaces in this list
7225 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7227 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7228 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7230 if (surface->lightmapinfo->samples)
7232 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7233 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7234 VectorScale(lm, scale, c);
7235 if (surface->lightmapinfo->styles[1] != 255)
7237 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7239 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7240 VectorMA(c, scale, lm, c);
7241 if (surface->lightmapinfo->styles[2] != 255)
7244 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7245 VectorMA(c, scale, lm, c);
7246 if (surface->lightmapinfo->styles[3] != 255)
7249 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7250 VectorMA(c, scale, lm, c);
7260 rsurface.lightmapcolor4f = rsurface.array_color4f;
7261 rsurface.lightmapcolor4f_bufferobject = 0;
7262 rsurface.lightmapcolor4f_bufferoffset = 0;
7266 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7267 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7268 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7270 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7271 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7272 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7273 GL_Color(r, g, b, a);
7274 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7277 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7279 int texturesurfaceindex;
7286 vec3_t ambientcolor;
7287 vec3_t diffusecolor;
7291 VectorCopy(rsurface.modellight_lightdir, lightdir);
7292 f = 0.5f * r_refdef.lightmapintensity;
7293 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7294 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7295 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7296 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7297 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7298 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7300 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7302 // generate color arrays for the surfaces in this list
7303 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7305 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7306 int numverts = surface->num_vertices;
7307 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7308 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7309 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7310 // q3-style directional shading
7311 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7313 if ((f = DotProduct(n, lightdir)) > 0)
7314 VectorMA(ambientcolor, f, diffusecolor, c);
7316 VectorCopy(ambientcolor, c);
7324 rsurface.lightmapcolor4f = rsurface.array_color4f;
7325 rsurface.lightmapcolor4f_bufferobject = 0;
7326 rsurface.lightmapcolor4f_bufferoffset = 0;
7327 *applycolor = false;
7331 *r = ambientcolor[0];
7332 *g = ambientcolor[1];
7333 *b = ambientcolor[2];
7334 rsurface.lightmapcolor4f = NULL;
7335 rsurface.lightmapcolor4f_bufferobject = 0;
7336 rsurface.lightmapcolor4f_bufferoffset = 0;
7340 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7342 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7343 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7344 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7345 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7346 GL_Color(r, g, b, a);
7347 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7350 void RSurf_SetupDepthAndCulling(void)
7352 // submodels are biased to avoid z-fighting with world surfaces that they
7353 // may be exactly overlapping (avoids z-fighting artifacts on certain
7354 // doors and things in Quake maps)
7355 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7356 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7357 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7358 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7361 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7363 // transparent sky would be ridiculous
7364 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7366 R_SetupGenericShader(false);
7367 skyrenderlater = true;
7368 RSurf_SetupDepthAndCulling();
7370 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7371 // skymasking on them, and Quake3 never did sky masking (unlike
7372 // software Quake and software Quake2), so disable the sky masking
7373 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7374 // and skymasking also looks very bad when noclipping outside the
7375 // level, so don't use it then either.
7376 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7378 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7379 R_Mesh_ColorPointer(NULL, 0, 0);
7380 R_Mesh_ResetTextureState();
7381 if (skyrendermasked)
7383 R_SetupDepthOrShadowShader();
7384 // depth-only (masking)
7385 GL_ColorMask(0,0,0,0);
7386 // just to make sure that braindead drivers don't draw
7387 // anything despite that colormask...
7388 GL_BlendFunc(GL_ZERO, GL_ONE);
7392 R_SetupGenericShader(false);
7394 GL_BlendFunc(GL_ONE, GL_ZERO);
7396 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7397 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7398 if (skyrendermasked)
7399 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7401 R_Mesh_ResetTextureState();
7402 GL_Color(1, 1, 1, 1);
7405 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7407 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7410 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7411 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7412 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7413 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7414 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7415 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7416 if (rsurface.texture->backgroundcurrentskinframe)
7418 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7419 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7420 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7421 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7423 if(rsurface.texture->colormapping)
7425 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7426 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7428 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7429 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7430 R_Mesh_ColorPointer(NULL, 0, 0);
7432 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7434 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7436 // render background
7437 GL_BlendFunc(GL_ONE, GL_ZERO);
7439 GL_AlphaTest(false);
7441 GL_Color(1, 1, 1, 1);
7442 R_Mesh_ColorPointer(NULL, 0, 0);
7444 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7445 if (r_glsl_permutation)
7447 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7448 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7449 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7450 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7451 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7452 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7453 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);
7455 GL_LockArrays(0, 0);
7457 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7458 GL_DepthMask(false);
7459 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7460 R_Mesh_ColorPointer(NULL, 0, 0);
7462 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7463 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7464 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7467 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7468 if (!r_glsl_permutation)
7471 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7472 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7473 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7474 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7475 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7476 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7478 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7480 GL_BlendFunc(GL_ONE, GL_ZERO);
7482 GL_AlphaTest(false);
7486 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7487 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7488 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7491 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7493 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7494 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);
7496 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7500 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7501 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);
7503 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7505 GL_LockArrays(0, 0);
7508 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7510 // OpenGL 1.3 path - anything not completely ancient
7511 int texturesurfaceindex;
7512 qboolean applycolor;
7516 const texturelayer_t *layer;
7517 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7519 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7522 int layertexrgbscale;
7523 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7525 if (layerindex == 0)
7529 GL_AlphaTest(false);
7530 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7533 GL_DepthMask(layer->depthmask && writedepth);
7534 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7535 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7537 layertexrgbscale = 4;
7538 VectorScale(layer->color, 0.25f, layercolor);
7540 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7542 layertexrgbscale = 2;
7543 VectorScale(layer->color, 0.5f, layercolor);
7547 layertexrgbscale = 1;
7548 VectorScale(layer->color, 1.0f, layercolor);
7550 layercolor[3] = layer->color[3];
7551 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7552 R_Mesh_ColorPointer(NULL, 0, 0);
7553 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7554 switch (layer->type)
7556 case TEXTURELAYERTYPE_LITTEXTURE:
7557 memset(&m, 0, sizeof(m));
7558 m.tex[0] = R_GetTexture(r_texture_white);
7559 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7560 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7561 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7562 m.tex[1] = R_GetTexture(layer->texture);
7563 m.texmatrix[1] = layer->texmatrix;
7564 m.texrgbscale[1] = layertexrgbscale;
7565 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7566 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7567 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7568 R_Mesh_TextureState(&m);
7569 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7570 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7571 else if (rsurface.uselightmaptexture)
7572 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7574 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7576 case TEXTURELAYERTYPE_TEXTURE:
7577 memset(&m, 0, sizeof(m));
7578 m.tex[0] = R_GetTexture(layer->texture);
7579 m.texmatrix[0] = layer->texmatrix;
7580 m.texrgbscale[0] = layertexrgbscale;
7581 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7582 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7583 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7584 R_Mesh_TextureState(&m);
7585 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7587 case TEXTURELAYERTYPE_FOG:
7588 memset(&m, 0, sizeof(m));
7589 m.texrgbscale[0] = layertexrgbscale;
7592 m.tex[0] = R_GetTexture(layer->texture);
7593 m.texmatrix[0] = layer->texmatrix;
7594 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7595 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7596 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7598 R_Mesh_TextureState(&m);
7599 // generate a color array for the fog pass
7600 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7601 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7607 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7608 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)
7610 f = 1 - RSurf_FogVertex(v);
7611 c[0] = layercolor[0];
7612 c[1] = layercolor[1];
7613 c[2] = layercolor[2];
7614 c[3] = f * layercolor[3];
7617 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7620 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7622 GL_LockArrays(0, 0);
7625 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7627 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7628 GL_AlphaTest(false);
7632 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7634 // OpenGL 1.1 - crusty old voodoo path
7635 int texturesurfaceindex;
7639 const texturelayer_t *layer;
7640 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7642 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7644 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7646 if (layerindex == 0)
7650 GL_AlphaTest(false);
7651 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7654 GL_DepthMask(layer->depthmask && writedepth);
7655 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7656 R_Mesh_ColorPointer(NULL, 0, 0);
7657 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7658 switch (layer->type)
7660 case TEXTURELAYERTYPE_LITTEXTURE:
7661 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7663 // two-pass lit texture with 2x rgbscale
7664 // first the lightmap pass
7665 memset(&m, 0, sizeof(m));
7666 m.tex[0] = R_GetTexture(r_texture_white);
7667 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7668 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7669 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7670 R_Mesh_TextureState(&m);
7671 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7672 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7673 else if (rsurface.uselightmaptexture)
7674 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7676 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7677 GL_LockArrays(0, 0);
7678 // then apply the texture to it
7679 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7680 memset(&m, 0, sizeof(m));
7681 m.tex[0] = R_GetTexture(layer->texture);
7682 m.texmatrix[0] = layer->texmatrix;
7683 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7684 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7685 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7686 R_Mesh_TextureState(&m);
7687 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);
7691 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7692 memset(&m, 0, sizeof(m));
7693 m.tex[0] = R_GetTexture(layer->texture);
7694 m.texmatrix[0] = layer->texmatrix;
7695 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7696 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7697 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7698 R_Mesh_TextureState(&m);
7699 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7700 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);
7702 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);
7705 case TEXTURELAYERTYPE_TEXTURE:
7706 // singletexture unlit texture with transparency support
7707 memset(&m, 0, sizeof(m));
7708 m.tex[0] = R_GetTexture(layer->texture);
7709 m.texmatrix[0] = layer->texmatrix;
7710 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7711 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7712 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7713 R_Mesh_TextureState(&m);
7714 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], 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);
7716 case TEXTURELAYERTYPE_FOG:
7717 // singletexture fogging
7718 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7721 memset(&m, 0, sizeof(m));
7722 m.tex[0] = R_GetTexture(layer->texture);
7723 m.texmatrix[0] = layer->texmatrix;
7724 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7725 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7726 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7727 R_Mesh_TextureState(&m);
7730 R_Mesh_ResetTextureState();
7731 // generate a color array for the fog pass
7732 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7738 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7739 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)
7741 f = 1 - RSurf_FogVertex(v);
7742 c[0] = layer->color[0];
7743 c[1] = layer->color[1];
7744 c[2] = layer->color[2];
7745 c[3] = f * layer->color[3];
7748 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7751 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7753 GL_LockArrays(0, 0);
7756 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7758 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7759 GL_AlphaTest(false);
7763 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7767 GL_AlphaTest(false);
7768 R_Mesh_ColorPointer(NULL, 0, 0);
7769 R_Mesh_ResetTextureState();
7770 R_SetupGenericShader(false);
7772 if(rsurface.texture && rsurface.texture->currentskinframe)
7774 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7775 c[3] *= rsurface.texture->currentalpha;
7785 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7787 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7788 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7789 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7792 // brighten it up (as texture value 127 means "unlit")
7793 c[0] *= 2 * r_refdef.view.colorscale;
7794 c[1] *= 2 * r_refdef.view.colorscale;
7795 c[2] *= 2 * r_refdef.view.colorscale;
7797 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7798 c[3] *= r_wateralpha.value;
7800 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7802 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7803 GL_DepthMask(false);
7805 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7807 GL_BlendFunc(GL_ONE, GL_ONE);
7808 GL_DepthMask(false);
7810 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7812 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7813 GL_DepthMask(false);
7815 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7817 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7818 GL_DepthMask(false);
7822 GL_BlendFunc(GL_ONE, GL_ZERO);
7823 GL_DepthMask(writedepth);
7826 rsurface.lightmapcolor4f = NULL;
7828 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7830 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7832 rsurface.lightmapcolor4f = NULL;
7833 rsurface.lightmapcolor4f_bufferobject = 0;
7834 rsurface.lightmapcolor4f_bufferoffset = 0;
7836 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7838 qboolean applycolor = true;
7841 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7843 r_refdef.lightmapintensity = 1;
7844 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7845 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7849 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7851 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7852 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7853 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7856 if(!rsurface.lightmapcolor4f)
7857 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7859 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7860 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7861 if(r_refdef.fogenabled)
7862 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7864 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7865 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7868 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7871 RSurf_SetupDepthAndCulling();
7872 if (r_showsurfaces.integer == 3)
7873 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7874 else if (r_glsl.integer && gl_support_fragment_shader)
7875 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7876 else if (gl_combine.integer && r_textureunits.integer >= 2)
7877 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7879 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7883 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7886 RSurf_SetupDepthAndCulling();
7887 if (r_showsurfaces.integer == 3)
7888 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7889 else if (r_glsl.integer && gl_support_fragment_shader)
7890 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7891 else if (gl_combine.integer && r_textureunits.integer >= 2)
7892 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7894 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7898 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7901 int texturenumsurfaces, endsurface;
7903 const msurface_t *surface;
7904 const msurface_t *texturesurfacelist[1024];
7906 // if the model is static it doesn't matter what value we give for
7907 // wantnormals and wanttangents, so this logic uses only rules applicable
7908 // to a model, knowing that they are meaningless otherwise
7909 if (ent == r_refdef.scene.worldentity)
7910 RSurf_ActiveWorldEntity();
7911 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7912 RSurf_ActiveModelEntity(ent, false, false);
7914 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7916 for (i = 0;i < numsurfaces;i = j)
7919 surface = rsurface.modelsurfaces + surfacelist[i];
7920 texture = surface->texture;
7921 rsurface.texture = R_GetCurrentTexture(texture);
7922 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7923 // scan ahead until we find a different texture
7924 endsurface = min(i + 1024, numsurfaces);
7925 texturenumsurfaces = 0;
7926 texturesurfacelist[texturenumsurfaces++] = surface;
7927 for (;j < endsurface;j++)
7929 surface = rsurface.modelsurfaces + surfacelist[j];
7930 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7932 texturesurfacelist[texturenumsurfaces++] = surface;
7934 // render the range of surfaces
7935 if (ent == r_refdef.scene.worldentity)
7936 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7938 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7940 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7941 GL_AlphaTest(false);
7944 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7946 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7950 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7952 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7954 RSurf_SetupDepthAndCulling();
7955 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7956 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7958 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7960 RSurf_SetupDepthAndCulling();
7961 GL_AlphaTest(false);
7962 R_Mesh_ColorPointer(NULL, 0, 0);
7963 R_Mesh_ResetTextureState();
7964 R_SetupGenericShader(false);
7965 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7967 GL_BlendFunc(GL_ONE, GL_ZERO);
7968 GL_Color(0, 0, 0, 1);
7969 GL_DepthTest(writedepth);
7970 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7972 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7974 RSurf_SetupDepthAndCulling();
7975 GL_AlphaTest(false);
7976 R_Mesh_ColorPointer(NULL, 0, 0);
7977 R_Mesh_ResetTextureState();
7978 R_SetupGenericShader(false);
7979 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7981 GL_BlendFunc(GL_ONE, GL_ZERO);
7983 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7985 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7986 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7987 else if (!rsurface.texture->currentnumlayers)
7989 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7991 // transparent surfaces get pushed off into the transparent queue
7992 int surfacelistindex;
7993 const msurface_t *surface;
7994 vec3_t tempcenter, center;
7995 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7997 surface = texturesurfacelist[surfacelistindex];
7998 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7999 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8000 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8001 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8002 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8007 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8008 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8013 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8017 // break the surface list down into batches by texture and use of lightmapping
8018 for (i = 0;i < numsurfaces;i = j)
8021 // texture is the base texture pointer, rsurface.texture is the
8022 // current frame/skin the texture is directing us to use (for example
8023 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8024 // use skin 1 instead)
8025 texture = surfacelist[i]->texture;
8026 rsurface.texture = R_GetCurrentTexture(texture);
8027 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8028 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8030 // if this texture is not the kind we want, skip ahead to the next one
8031 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8035 // simply scan ahead until we find a different texture or lightmap state
8036 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8038 // render the range of surfaces
8039 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
8043 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
8048 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8050 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8052 RSurf_SetupDepthAndCulling();
8053 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8054 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8056 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8058 RSurf_SetupDepthAndCulling();
8059 GL_AlphaTest(false);
8060 R_Mesh_ColorPointer(NULL, 0, 0);
8061 R_Mesh_ResetTextureState();
8062 R_SetupGenericShader(false);
8063 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8065 GL_BlendFunc(GL_ONE, GL_ZERO);
8066 GL_Color(0, 0, 0, 1);
8067 GL_DepthTest(writedepth);
8068 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8070 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8072 RSurf_SetupDepthAndCulling();
8073 GL_AlphaTest(false);
8074 R_Mesh_ColorPointer(NULL, 0, 0);
8075 R_Mesh_ResetTextureState();
8076 R_SetupGenericShader(false);
8077 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8079 GL_BlendFunc(GL_ONE, GL_ZERO);
8081 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8083 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8084 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8085 else if (!rsurface.texture->currentnumlayers)
8087 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8089 // transparent surfaces get pushed off into the transparent queue
8090 int surfacelistindex;
8091 const msurface_t *surface;
8092 vec3_t tempcenter, center;
8093 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8095 surface = texturesurfacelist[surfacelistindex];
8096 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8097 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8098 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8099 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8100 if (queueentity->transparent_offset) // transparent offset
8102 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8103 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8104 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8106 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8111 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8112 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8117 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8121 // break the surface list down into batches by texture and use of lightmapping
8122 for (i = 0;i < numsurfaces;i = j)
8125 // texture is the base texture pointer, rsurface.texture is the
8126 // current frame/skin the texture is directing us to use (for example
8127 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8128 // use skin 1 instead)
8129 texture = surfacelist[i]->texture;
8130 rsurface.texture = R_GetCurrentTexture(texture);
8131 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8132 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8134 // if this texture is not the kind we want, skip ahead to the next one
8135 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8139 // simply scan ahead until we find a different texture or lightmap state
8140 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8142 // render the range of surfaces
8143 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8147 float locboxvertex3f[6*4*3] =
8149 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8150 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8151 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8152 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8153 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8154 1,0,0, 0,0,0, 0,1,0, 1,1,0
8157 unsigned short locboxelements[6*2*3] =
8167 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8170 cl_locnode_t *loc = (cl_locnode_t *)ent;
8172 float vertex3f[6*4*3];
8174 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8175 GL_DepthMask(false);
8176 GL_DepthRange(0, 1);
8177 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8179 GL_CullFace(GL_NONE);
8180 R_Mesh_Matrix(&identitymatrix);
8182 R_Mesh_VertexPointer(vertex3f, 0, 0);
8183 R_Mesh_ColorPointer(NULL, 0, 0);
8184 R_Mesh_ResetTextureState();
8185 R_SetupGenericShader(false);
8188 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8189 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8190 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8191 surfacelist[0] < 0 ? 0.5f : 0.125f);
8193 if (VectorCompare(loc->mins, loc->maxs))
8195 VectorSet(size, 2, 2, 2);
8196 VectorMA(loc->mins, -0.5f, size, mins);
8200 VectorCopy(loc->mins, mins);
8201 VectorSubtract(loc->maxs, loc->mins, size);
8204 for (i = 0;i < 6*4*3;)
8205 for (j = 0;j < 3;j++, i++)
8206 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8208 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8211 void R_DrawLocs(void)
8214 cl_locnode_t *loc, *nearestloc;
8216 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8217 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8219 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8220 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8224 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8226 if (decalsystem->decals)
8227 Mem_Free(decalsystem->decals);
8228 memset(decalsystem, 0, sizeof(*decalsystem));
8231 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)
8242 // expand or initialize the system
8243 if (decalsystem->maxdecals <= decalsystem->numdecals)
8245 decalsystem_t old = *decalsystem;
8246 qboolean useshortelements;
8247 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8248 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8249 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)));
8250 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8251 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8252 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8253 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8254 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8255 if (decalsystem->numdecals)
8257 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8258 memcpy(decalsystem->vertex3f, old.vertex3f, decalsystem->numdecals * sizeof(float[3][3]));
8259 memcpy(decalsystem->texcoord2f, old.texcoord2f, decalsystem->numdecals * sizeof(float[3][2]));
8260 memcpy(decalsystem->color4f, old.color4f, decalsystem->numdecals * sizeof(float[3][4]));
8262 Mem_Free(old.decals);
8263 for (i = 0;i < decalsystem->maxdecals*3;i++)
8264 decalsystem->element3i[i] = i;
8265 if (useshortelements)
8266 for (i = 0;i < decalsystem->maxdecals*3;i++)
8267 decalsystem->element3s[i] = i;
8270 // grab a decal and search for another free slot for the next one
8271 maxdecals = decalsystem->maxdecals;
8272 decals = decalsystem->decals;
8273 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8274 v3f = decalsystem->vertex3f + 9*i;
8275 tc2f = decalsystem->texcoord2f + 6*i;
8276 c4f = decalsystem->color4f + 12*i;
8277 for (i = decalsystem->freedecal;i < maxdecals && decals[i].colors[0][3];i++)
8279 decalsystem->freedecal = i;
8280 if (decalsystem->numdecals <= i)
8281 decalsystem->numdecals = i + 1;
8283 // initialize the decal
8285 decal->triangleindex = triangleindex;
8286 decal->colors[0][0] = (unsigned char)(c0[0]*255.0f);
8287 decal->colors[0][1] = (unsigned char)(c0[1]*255.0f);
8288 decal->colors[0][2] = (unsigned char)(c0[2]*255.0f);
8289 decal->colors[0][3] = 255;
8290 decal->colors[1][0] = (unsigned char)(c1[0]*255.0f);
8291 decal->colors[1][1] = (unsigned char)(c1[1]*255.0f);
8292 decal->colors[1][2] = (unsigned char)(c1[2]*255.0f);
8293 decal->colors[1][3] = 255;
8294 decal->colors[2][0] = (unsigned char)(c2[0]*255.0f);
8295 decal->colors[2][1] = (unsigned char)(c2[1]*255.0f);
8296 decal->colors[2][2] = (unsigned char)(c2[2]*255.0f);
8297 decal->colors[2][3] = 255;
8314 c4f[ 0] = decal->colors[0][0] * ca;
8315 c4f[ 1] = decal->colors[0][1] * ca;
8316 c4f[ 2] = decal->colors[0][2] * ca;
8318 c4f[ 4] = decal->colors[1][0] * ca;
8319 c4f[ 5] = decal->colors[1][1] * ca;
8320 c4f[ 6] = decal->colors[1][2] * ca;
8322 c4f[ 8] = decal->colors[2][0] * ca;
8323 c4f[ 9] = decal->colors[2][1] * ca;
8324 c4f[10] = decal->colors[2][2] * ca;
8328 extern cvar_t cl_decals_bias;
8329 extern cvar_t cl_decals_models;
8330 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8331 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)
8333 matrix4x4_t projection;
8334 decalsystem_t *decalsystem;
8337 const float *vertex3f;
8338 const msurface_t *surface;
8339 const msurface_t *surfaces;
8340 const int *surfacelist;
8341 const texture_t *texture;
8345 int surfacelistindex;
8351 float localorigin[3];
8352 float localnormal[3];
8363 float points[2][9][3];
8367 decalsystem = &ent->decalsystem;
8369 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8371 R_DecalSystem_Reset(&ent->decalsystem);
8375 if (!model->brush.data_nodes && !cl_decals_models.integer)
8377 if (decalsystem->model)
8378 R_DecalSystem_Reset(decalsystem);
8382 if (decalsystem->model != model)
8383 R_DecalSystem_Reset(decalsystem);
8384 decalsystem->model = model;
8386 RSurf_ActiveModelEntity(ent, false, false);
8388 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8389 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8390 VectorNormalize(localnormal);
8391 localsize = worldsize*rsurface.inversematrixscale;
8392 ilocalsize = 1.0f / localsize;
8393 localmins[0] = localorigin[0] - localsize;
8394 localmins[1] = localorigin[1] - localsize;
8395 localmins[2] = localorigin[2] - localsize;
8396 localmaxs[0] = localorigin[0] + localsize;
8397 localmaxs[1] = localorigin[1] + localsize;
8398 localmaxs[2] = localorigin[2] + localsize;
8400 //VectorCopy(localnormal, planes[4]);
8401 //VectorVectors(planes[4], planes[2], planes[0]);
8402 AnglesFromVectors(angles, localnormal, NULL, false);
8403 AngleVectors(angles, planes[0], planes[2], planes[4]);
8404 VectorNegate(planes[0], planes[1]);
8405 VectorNegate(planes[2], planes[3]);
8406 VectorNegate(planes[4], planes[5]);
8407 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8408 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8409 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8410 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8411 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8412 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8417 matrix4x4_t forwardprojection;
8418 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8419 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8424 float projectionvector[4][3];
8425 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8426 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8427 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8428 projectionvector[0][0] = planes[0][0] * ilocalsize;
8429 projectionvector[0][1] = planes[1][0] * ilocalsize;
8430 projectionvector[0][2] = planes[2][0] * ilocalsize;
8431 projectionvector[1][0] = planes[0][1] * ilocalsize;
8432 projectionvector[1][1] = planes[1][1] * ilocalsize;
8433 projectionvector[1][2] = planes[2][1] * ilocalsize;
8434 projectionvector[2][0] = planes[0][2] * ilocalsize;
8435 projectionvector[2][1] = planes[1][2] * ilocalsize;
8436 projectionvector[2][2] = planes[2][2] * ilocalsize;
8437 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8438 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8439 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8440 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8444 dynamic = model->surfmesh.isanimated;
8445 vertex3f = rsurface.modelvertex3f;
8446 numsurfacelist = model->nummodelsurfaces;
8447 surfacelist = model->sortedmodelsurfaces;
8448 surfaces = model->data_surfaces;
8449 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8451 surface = surfaces + surfacelist[surfacelistindex];
8452 // skip transparent surfaces
8453 texture = surface->texture;
8454 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8456 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8458 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8460 numvertices = surface->num_vertices;
8461 numtriangles = surface->num_triangles;
8462 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8464 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8466 index = 3*e[cornerindex];
8467 VectorCopy(vertex3f + index, v[cornerindex]);
8470 //TriangleNormal(v[0], v[1], v[2], normal);
8471 //if (DotProduct(normal, localnormal) < 0.0f)
8473 // clip by each of the box planes formed from the projection matrix
8474 // if anything survives, we emit the decal
8475 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]);
8478 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]);
8481 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]);
8484 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]);
8487 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]);
8490 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]);
8493 // some part of the triangle survived, so we have to accept it...
8496 // dynamic always uses the original triangle
8498 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8500 index = 3*e[cornerindex];
8501 VectorCopy(vertex3f + index, v[cornerindex]);
8504 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8506 // convert vertex positions to texcoords
8507 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8508 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8509 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8510 // calculate distance fade from the projection origin
8511 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8512 f = bound(0.0f, f, 1.0f);
8513 c[cornerindex][0] = r * f;
8514 c[cornerindex][1] = g * f;
8515 c[cornerindex][2] = b * f;
8516 c[cornerindex][3] = 1.0f;
8517 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8520 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);
8522 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8523 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);
8528 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8529 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)
8531 int renderentityindex;
8534 entity_render_t *ent;
8536 if (!cl_decals_newsystem.integer)
8539 worldmins[0] = worldorigin[0] - worldsize;
8540 worldmins[1] = worldorigin[1] - worldsize;
8541 worldmins[2] = worldorigin[2] - worldsize;
8542 worldmaxs[0] = worldorigin[0] + worldsize;
8543 worldmaxs[1] = worldorigin[1] + worldsize;
8544 worldmaxs[2] = worldorigin[2] + worldsize;
8546 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8548 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8550 ent = r_refdef.scene.entities[renderentityindex];
8551 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8554 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8558 typedef struct r_decalsystem_splatqueue_s
8566 r_decalsystem_splatqueue_t;
8568 int r_decalsystem_queuestart = 0;
8569 int r_decalsystem_queueend = 0;
8570 #define MAX_DECALSYSTEM_QUEUE 128
8571 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8573 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)
8575 r_decalsystem_splatqueue_t *queue;
8577 if (!cl_decals_newsystem.integer)
8580 queue = &r_decalsystem_queue[(r_decalsystem_queueend++) % MAX_DECALSYSTEM_QUEUE];
8581 VectorCopy(worldorigin, queue->worldorigin);
8582 VectorCopy(worldnormal, queue->worldnormal);
8583 Vector4Set(queue->color, r, g, b, a);
8584 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8585 queue->worldsize = worldsize;
8588 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8590 r_decalsystem_splatqueue_t *queue;
8592 r_decalsystem_queuestart = max(r_decalsystem_queuestart, r_decalsystem_queueend - MAX_DECALSYSTEM_QUEUE);
8593 while (r_decalsystem_queuestart < r_decalsystem_queueend)
8595 queue = &r_decalsystem_queue[(r_decalsystem_queuestart++) % MAX_DECALSYSTEM_QUEUE];
8596 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);
8600 extern skinframe_t *decalskinframe;
8601 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8604 decalsystem_t *decalsystem = &ent->decalsystem;
8615 if (!decalsystem->numdecals)
8618 if (r_showsurfaces.integer)
8621 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8623 R_DecalSystem_Reset(decalsystem);
8627 // if the model is static it doesn't matter what value we give for
8628 // wantnormals and wanttangents, so this logic uses only rules applicable
8629 // to a model, knowing that they are meaningless otherwise
8630 if (ent == r_refdef.scene.worldentity)
8631 RSurf_ActiveWorldEntity();
8633 RSurf_ActiveModelEntity(ent, false, false);
8635 if (decalsystem->lastupdatetime)
8636 frametime = cl.time - decalsystem->lastupdatetime;
8639 decalsystem->lastupdatetime = cl.time;
8640 decal = decalsystem->decals;
8641 numdecals = decalsystem->numdecals;
8643 fadedelay = cl_decals_time.value;
8644 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
8646 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8648 if (!decal->colors[0][3])
8651 decal->lived += frametime;
8652 if (decal->lived >= fadedelay)
8654 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
8657 // kill the decal by zeroing vertex data
8658 memset(decalsystem->vertex3f + 9*i, 0, sizeof(float[3][3]));
8659 memset(decalsystem->texcoord2f + 6*i, 0, sizeof(float[3][2]));
8660 memset(decalsystem->color4f + 12*i, 0, sizeof(float[3][4]));
8661 memset(decal, 0, sizeof(*decal));
8662 if (decalsystem->freedecal > i)
8663 decalsystem->freedecal = i;
8667 // update color values for fading decals
8668 alpha *= (1.0f/255.0f);
8669 c4f = decalsystem->color4f + 12*i;
8670 c4f[ 0] = decal->colors[0][0] * alpha;
8671 c4f[ 1] = decal->colors[0][1] * alpha;
8672 c4f[ 2] = decal->colors[0][2] * alpha;
8674 c4f[ 4] = decal->colors[1][0] * alpha;
8675 c4f[ 5] = decal->colors[1][1] * alpha;
8676 c4f[ 6] = decal->colors[1][2] * alpha;
8678 c4f[ 8] = decal->colors[2][0] * alpha;
8679 c4f[ 9] = decal->colors[2][1] * alpha;
8680 c4f[10] = decal->colors[2][2] * alpha;
8684 // update vertex positions for animated models
8685 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8687 e = rsurface.modelelement3i + 3*decal->triangleindex;
8688 v3f = decalsystem->vertex3f + 9*i;
8689 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8690 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8691 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8695 // reduce numdecals if possible
8696 while (numdecals > 0 && !decalsystem->decals[numdecals - 1].colors[0][3])
8698 decalsystem->numdecals = numdecals;
8702 r_refdef.stats.decals += numdecals;
8703 // now render the decals all at once
8704 // (this assumes they all use one particle font texture!)
8705 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numdecals, decalsystem->element3i, decalsystem->element3s, false, false);
8706 R_Mesh_ResetTextureState();
8707 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8708 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8709 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8710 R_SetupGenericShader(true);
8711 GL_DepthMask(false);
8712 GL_DepthRange(0, 1);
8713 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
8715 GL_CullFace(GL_NONE);
8716 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8717 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8718 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8719 GL_LockArrays(0, numdecals * 3);
8720 R_Mesh_Draw(0, numdecals * 3, 0, numdecals, decalsystem->element3i, decalsystem->element3s, 0, 0);
8721 GL_LockArrays(0, 0);
8726 // if there are no decals left, reset decalsystem
8727 R_DecalSystem_Reset(decalsystem);
8731 void R_DrawDebugModel(void)
8733 entity_render_t *ent = rsurface.entity;
8734 int i, j, k, l, flagsmask;
8735 const int *elements;
8737 const msurface_t *surface;
8738 dp_model_t *model = ent->model;
8741 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8743 R_Mesh_ColorPointer(NULL, 0, 0);
8744 R_Mesh_ResetTextureState();
8745 R_SetupGenericShader(false);
8746 GL_DepthRange(0, 1);
8747 GL_DepthTest(!r_showdisabledepthtest.integer);
8748 GL_DepthMask(false);
8749 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8751 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8753 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8754 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8756 if (brush->colbrushf && brush->colbrushf->numtriangles)
8758 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8759 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);
8760 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8763 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8765 if (surface->num_collisiontriangles)
8767 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8768 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);
8769 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8774 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8776 if (r_showtris.integer || r_shownormals.integer)
8778 if (r_showdisabledepthtest.integer)
8780 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8781 GL_DepthMask(false);
8785 GL_BlendFunc(GL_ONE, GL_ZERO);
8788 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8790 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8792 rsurface.texture = R_GetCurrentTexture(surface->texture);
8793 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8795 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8796 if (r_showtris.value > 0)
8798 if (!rsurface.texture->currentlayers->depthmask)
8799 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8800 else if (ent == r_refdef.scene.worldentity)
8801 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8803 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8804 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8805 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8806 R_Mesh_ColorPointer(NULL, 0, 0);
8807 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8808 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8809 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8810 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);
8811 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8814 if (r_shownormals.value < 0)
8817 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8819 VectorCopy(rsurface.vertex3f + l * 3, v);
8820 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8821 qglVertex3f(v[0], v[1], v[2]);
8822 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8823 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8824 qglVertex3f(v[0], v[1], v[2]);
8829 if (r_shownormals.value > 0)
8832 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8834 VectorCopy(rsurface.vertex3f + l * 3, v);
8835 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8836 qglVertex3f(v[0], v[1], v[2]);
8837 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8838 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8839 qglVertex3f(v[0], v[1], v[2]);
8844 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8846 VectorCopy(rsurface.vertex3f + l * 3, v);
8847 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8848 qglVertex3f(v[0], v[1], v[2]);
8849 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8850 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8851 qglVertex3f(v[0], v[1], v[2]);
8856 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8858 VectorCopy(rsurface.vertex3f + l * 3, v);
8859 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8860 qglVertex3f(v[0], v[1], v[2]);
8861 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8862 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8863 qglVertex3f(v[0], v[1], v[2]);
8870 rsurface.texture = NULL;
8874 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8875 int r_maxsurfacelist = 0;
8876 const msurface_t **r_surfacelist = NULL;
8877 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8879 int i, j, endj, f, flagsmask;
8881 dp_model_t *model = r_refdef.scene.worldmodel;
8882 msurface_t *surfaces;
8883 unsigned char *update;
8884 int numsurfacelist = 0;
8888 if (r_maxsurfacelist < model->num_surfaces)
8890 r_maxsurfacelist = model->num_surfaces;
8892 Mem_Free(r_surfacelist);
8893 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8896 RSurf_ActiveWorldEntity();
8898 surfaces = model->data_surfaces;
8899 update = model->brushq1.lightmapupdateflags;
8901 // update light styles on this submodel
8902 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8904 model_brush_lightstyleinfo_t *style;
8905 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8907 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8909 int *list = style->surfacelist;
8910 style->value = r_refdef.scene.lightstylevalue[style->style];
8911 for (j = 0;j < style->numsurfaces;j++)
8912 update[list[j]] = true;
8917 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8922 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8928 rsurface.uselightmaptexture = false;
8929 rsurface.texture = NULL;
8930 rsurface.rtlight = NULL;
8932 // add visible surfaces to draw list
8933 for (i = 0;i < model->nummodelsurfaces;i++)
8935 j = model->sortedmodelsurfaces[i];
8936 if (r_refdef.viewcache.world_surfacevisible[j])
8937 r_surfacelist[numsurfacelist++] = surfaces + j;
8939 // update lightmaps if needed
8941 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8942 if (r_refdef.viewcache.world_surfacevisible[j])
8944 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8945 // don't do anything if there were no surfaces
8946 if (!numsurfacelist)
8948 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8951 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8952 GL_AlphaTest(false);
8954 // add to stats if desired
8955 if (r_speeds.integer && !skysurfaces && !depthonly)
8957 r_refdef.stats.world_surfaces += numsurfacelist;
8958 for (j = 0;j < numsurfacelist;j++)
8959 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8962 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8965 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8967 int i, j, endj, f, flagsmask;
8969 dp_model_t *model = ent->model;
8970 msurface_t *surfaces;
8971 unsigned char *update;
8972 int numsurfacelist = 0;
8976 if (r_maxsurfacelist < model->num_surfaces)
8978 r_maxsurfacelist = model->num_surfaces;
8980 Mem_Free(r_surfacelist);
8981 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8984 // if the model is static it doesn't matter what value we give for
8985 // wantnormals and wanttangents, so this logic uses only rules applicable
8986 // to a model, knowing that they are meaningless otherwise
8987 if (ent == r_refdef.scene.worldentity)
8988 RSurf_ActiveWorldEntity();
8989 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8990 RSurf_ActiveModelEntity(ent, false, false);
8992 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8994 surfaces = model->data_surfaces;
8995 update = model->brushq1.lightmapupdateflags;
8997 // update light styles
8998 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9000 model_brush_lightstyleinfo_t *style;
9001 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9003 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9005 int *list = style->surfacelist;
9006 style->value = r_refdef.scene.lightstylevalue[style->style];
9007 for (j = 0;j < style->numsurfaces;j++)
9008 update[list[j]] = true;
9013 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9018 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9024 rsurface.uselightmaptexture = false;
9025 rsurface.texture = NULL;
9026 rsurface.rtlight = NULL;
9028 // add visible surfaces to draw list
9029 for (i = 0;i < model->nummodelsurfaces;i++)
9030 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9031 // don't do anything if there were no surfaces
9032 if (!numsurfacelist)
9034 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9037 // update lightmaps if needed
9039 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9041 R_BuildLightMap(ent, surfaces + j);
9042 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
9043 GL_AlphaTest(false);
9045 // add to stats if desired
9046 if (r_speeds.integer && !skysurfaces && !depthonly)
9048 r_refdef.stats.entities_surfaces += numsurfacelist;
9049 for (j = 0;j < numsurfacelist;j++)
9050 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9053 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9056 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
9058 static texture_t texture;
9059 static msurface_t surface;
9060 const msurface_t *surfacelist = &surface;
9062 // fake enough texture and surface state to render this geometry
9064 texture.update_lastrenderframe = -1; // regenerate this texture
9065 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9066 texture.currentskinframe = skinframe;
9067 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9068 texture.specularscalemod = 1;
9069 texture.specularpowermod = 1;
9071 surface.texture = &texture;
9072 surface.num_triangles = numtriangles;
9073 surface.num_firsttriangle = firsttriangle;
9074 surface.num_vertices = numvertices;
9075 surface.num_firstvertex = firstvertex;
9078 rsurface.texture = R_GetCurrentTexture(surface.texture);
9079 rsurface.uselightmaptexture = false;
9080 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);