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, ent->skeleton, 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, ent->skeleton, 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_View_SetFrustum(void)
3720 double slopex, slopey;
3721 vec3_t forward, left, up, origin;
3723 // we can't trust r_refdef.view.forward and friends in reflected scenes
3724 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3727 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3728 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3729 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3730 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3731 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3732 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3733 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3734 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3735 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3736 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3737 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3738 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3742 zNear = r_refdef.nearclip;
3743 nudge = 1.0 - 1.0 / (1<<23);
3744 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3745 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3746 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3747 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3748 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3749 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3750 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3751 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3757 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3758 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3759 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3760 r_refdef.view.frustum[0].dist = m[15] - m[12];
3762 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3763 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3764 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3765 r_refdef.view.frustum[1].dist = m[15] + m[12];
3767 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3768 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3769 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3770 r_refdef.view.frustum[2].dist = m[15] - m[13];
3772 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3773 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3774 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3775 r_refdef.view.frustum[3].dist = m[15] + m[13];
3777 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3778 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3779 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3780 r_refdef.view.frustum[4].dist = m[15] - m[14];
3782 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3783 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3784 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3785 r_refdef.view.frustum[5].dist = m[15] + m[14];
3788 if (r_refdef.view.useperspective)
3790 slopex = 1.0 / r_refdef.view.frustum_x;
3791 slopey = 1.0 / r_refdef.view.frustum_y;
3792 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3793 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3794 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3795 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3796 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3798 // Leaving those out was a mistake, those were in the old code, and they
3799 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3800 // I couldn't reproduce it after adding those normalizations. --blub
3801 VectorNormalize(r_refdef.view.frustum[0].normal);
3802 VectorNormalize(r_refdef.view.frustum[1].normal);
3803 VectorNormalize(r_refdef.view.frustum[2].normal);
3804 VectorNormalize(r_refdef.view.frustum[3].normal);
3806 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3807 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]);
3808 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]);
3809 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]);
3810 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]);
3812 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3813 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3814 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3815 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3816 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3820 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3821 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3822 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3823 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3824 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3825 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3826 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3827 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3828 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3829 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3831 r_refdef.view.numfrustumplanes = 5;
3833 if (r_refdef.view.useclipplane)
3835 r_refdef.view.numfrustumplanes = 6;
3836 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3839 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3840 PlaneClassify(r_refdef.view.frustum + i);
3842 // LordHavoc: note to all quake engine coders, Quake had a special case
3843 // for 90 degrees which assumed a square view (wrong), so I removed it,
3844 // Quake2 has it disabled as well.
3846 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3847 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3848 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3849 //PlaneClassify(&frustum[0]);
3851 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3852 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3853 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3854 //PlaneClassify(&frustum[1]);
3856 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3857 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3858 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3859 //PlaneClassify(&frustum[2]);
3861 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3862 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3863 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3864 //PlaneClassify(&frustum[3]);
3867 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3868 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3869 //PlaneClassify(&frustum[4]);
3872 void R_View_Update(void)
3874 R_Main_ResizeViewCache();
3875 R_View_SetFrustum();
3876 R_View_WorldVisibility(r_refdef.view.useclipplane);
3877 R_View_UpdateEntityVisible();
3878 R_View_UpdateEntityLighting();
3881 void R_SetupView(qboolean allowwaterclippingplane)
3883 const double *customclipplane = NULL;
3885 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3887 // LordHavoc: couldn't figure out how to make this approach the
3888 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3889 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3890 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3891 dist = r_refdef.view.clipplane.dist;
3892 plane[0] = r_refdef.view.clipplane.normal[0];
3893 plane[1] = r_refdef.view.clipplane.normal[1];
3894 plane[2] = r_refdef.view.clipplane.normal[2];
3896 customclipplane = plane;
3899 if (!r_refdef.view.useperspective)
3900 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);
3901 else if (gl_stencil && r_useinfinitefarclip.integer)
3902 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);
3904 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);
3905 R_SetViewport(&r_refdef.view.viewport);
3908 void R_ResetViewRendering2D(void)
3910 r_viewport_t viewport;
3913 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3914 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);
3915 R_SetViewport(&viewport);
3916 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3917 GL_Color(1, 1, 1, 1);
3918 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3919 GL_BlendFunc(GL_ONE, GL_ZERO);
3920 GL_AlphaTest(false);
3921 GL_ScissorTest(false);
3922 GL_DepthMask(false);
3923 GL_DepthRange(0, 1);
3924 GL_DepthTest(false);
3925 R_Mesh_Matrix(&identitymatrix);
3926 R_Mesh_ResetTextureState();
3927 GL_PolygonOffset(0, 0);
3928 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3929 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3930 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3931 qglStencilMask(~0);CHECKGLERROR
3932 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3933 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3934 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3935 R_SetupGenericShader(true);
3938 void R_ResetViewRendering3D(void)
3943 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3944 GL_Color(1, 1, 1, 1);
3945 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3946 GL_BlendFunc(GL_ONE, GL_ZERO);
3947 GL_AlphaTest(false);
3948 GL_ScissorTest(true);
3950 GL_DepthRange(0, 1);
3952 R_Mesh_Matrix(&identitymatrix);
3953 R_Mesh_ResetTextureState();
3954 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3955 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3956 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3957 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3958 qglStencilMask(~0);CHECKGLERROR
3959 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3960 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3961 GL_CullFace(r_refdef.view.cullface_back);
3962 R_SetupGenericShader(true);
3965 void R_RenderScene(void);
3966 void R_RenderWaterPlanes(void);
3968 static void R_Water_StartFrame(void)
3971 int waterwidth, waterheight, texturewidth, textureheight;
3972 r_waterstate_waterplane_t *p;
3974 // set waterwidth and waterheight to the water resolution that will be
3975 // used (often less than the screen resolution for faster rendering)
3976 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3977 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3979 // calculate desired texture sizes
3980 // can't use water if the card does not support the texture size
3981 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3982 texturewidth = textureheight = waterwidth = waterheight = 0;
3983 else if (gl_support_arb_texture_non_power_of_two)
3985 texturewidth = waterwidth;
3986 textureheight = waterheight;
3990 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3991 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3994 // allocate textures as needed
3995 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3997 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3998 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4000 if (p->texture_refraction)
4001 R_FreeTexture(p->texture_refraction);
4002 p->texture_refraction = NULL;
4003 if (p->texture_reflection)
4004 R_FreeTexture(p->texture_reflection);
4005 p->texture_reflection = NULL;
4007 memset(&r_waterstate, 0, sizeof(r_waterstate));
4008 r_waterstate.texturewidth = texturewidth;
4009 r_waterstate.textureheight = textureheight;
4012 if (r_waterstate.texturewidth)
4014 r_waterstate.enabled = true;
4016 // when doing a reduced render (HDR) we want to use a smaller area
4017 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4018 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4020 // set up variables that will be used in shader setup
4021 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4022 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4023 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4024 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4027 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4028 r_waterstate.numwaterplanes = 0;
4031 void R_Water_AddWaterPlane(msurface_t *surface)
4033 int triangleindex, planeindex;
4039 r_waterstate_waterplane_t *p;
4040 texture_t *t = R_GetCurrentTexture(surface->texture);
4041 // just use the first triangle with a valid normal for any decisions
4042 VectorClear(normal);
4043 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4045 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4046 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4047 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4048 TriangleNormal(vert[0], vert[1], vert[2], normal);
4049 if (VectorLength2(normal) >= 0.001)
4053 VectorCopy(normal, plane.normal);
4054 VectorNormalize(plane.normal);
4055 plane.dist = DotProduct(vert[0], plane.normal);
4056 PlaneClassify(&plane);
4057 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4059 // skip backfaces (except if nocullface is set)
4060 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4062 VectorNegate(plane.normal, plane.normal);
4064 PlaneClassify(&plane);
4068 // find a matching plane if there is one
4069 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4070 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4072 if (planeindex >= r_waterstate.maxwaterplanes)
4073 return; // nothing we can do, out of planes
4075 // if this triangle does not fit any known plane rendered this frame, add one
4076 if (planeindex >= r_waterstate.numwaterplanes)
4078 // store the new plane
4079 r_waterstate.numwaterplanes++;
4081 // clear materialflags and pvs
4082 p->materialflags = 0;
4083 p->pvsvalid = false;
4085 // merge this surface's materialflags into the waterplane
4086 p->materialflags |= t->currentmaterialflags;
4087 // merge this surface's PVS into the waterplane
4088 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4089 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4090 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4092 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4097 static void R_Water_ProcessPlanes(void)
4099 r_refdef_view_t originalview;
4100 r_refdef_view_t myview;
4102 r_waterstate_waterplane_t *p;
4104 originalview = r_refdef.view;
4106 // make sure enough textures are allocated
4107 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4109 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4111 if (!p->texture_refraction)
4112 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);
4113 if (!p->texture_refraction)
4117 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4119 if (!p->texture_reflection)
4120 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);
4121 if (!p->texture_reflection)
4127 r_refdef.view = originalview;
4128 r_refdef.view.showdebug = false;
4129 r_refdef.view.width = r_waterstate.waterwidth;
4130 r_refdef.view.height = r_waterstate.waterheight;
4131 r_refdef.view.useclipplane = true;
4132 myview = r_refdef.view;
4133 r_waterstate.renderingscene = true;
4134 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4136 // render the normal view scene and copy into texture
4137 // (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)
4138 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4140 r_refdef.view = myview;
4141 r_refdef.view.clipplane = p->plane;
4142 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4143 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4144 PlaneClassify(&r_refdef.view.clipplane);
4146 R_ResetViewRendering3D();
4147 R_ClearScreen(r_refdef.fogenabled);
4151 // copy view into the screen texture
4152 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4153 GL_ActiveTexture(0);
4155 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
4158 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4160 r_refdef.view = myview;
4161 // render reflected scene and copy into texture
4162 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4163 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4164 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4165 r_refdef.view.clipplane = p->plane;
4166 // reverse the cullface settings for this render
4167 r_refdef.view.cullface_front = GL_FRONT;
4168 r_refdef.view.cullface_back = GL_BACK;
4169 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4171 r_refdef.view.usecustompvs = true;
4173 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4175 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4178 R_ResetViewRendering3D();
4179 R_ClearScreen(r_refdef.fogenabled);
4183 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4184 GL_ActiveTexture(0);
4186 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
4189 r_waterstate.renderingscene = false;
4190 r_refdef.view = originalview;
4191 R_ResetViewRendering3D();
4192 R_ClearScreen(r_refdef.fogenabled);
4196 r_refdef.view = originalview;
4197 r_waterstate.renderingscene = false;
4198 Cvar_SetValueQuick(&r_water, 0);
4199 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4203 void R_Bloom_StartFrame(void)
4205 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4207 // set bloomwidth and bloomheight to the bloom resolution that will be
4208 // used (often less than the screen resolution for faster rendering)
4209 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4210 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4211 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4212 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
4213 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
4215 // calculate desired texture sizes
4216 if (gl_support_arb_texture_non_power_of_two)
4218 screentexturewidth = r_refdef.view.width;
4219 screentextureheight = r_refdef.view.height;
4220 bloomtexturewidth = r_bloomstate.bloomwidth;
4221 bloomtextureheight = r_bloomstate.bloomheight;
4225 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4226 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4227 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4228 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4231 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))
4233 Cvar_SetValueQuick(&r_hdr, 0);
4234 Cvar_SetValueQuick(&r_bloom, 0);
4235 Cvar_SetValueQuick(&r_motionblur, 0);
4236 Cvar_SetValueQuick(&r_damageblur, 0);
4239 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)))
4240 screentexturewidth = screentextureheight = 0;
4241 if (!r_hdr.integer && !r_bloom.integer)
4242 bloomtexturewidth = bloomtextureheight = 0;
4244 // allocate textures as needed
4245 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4247 if (r_bloomstate.texture_screen)
4248 R_FreeTexture(r_bloomstate.texture_screen);
4249 r_bloomstate.texture_screen = NULL;
4250 r_bloomstate.screentexturewidth = screentexturewidth;
4251 r_bloomstate.screentextureheight = screentextureheight;
4252 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4253 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);
4255 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4257 if (r_bloomstate.texture_bloom)
4258 R_FreeTexture(r_bloomstate.texture_bloom);
4259 r_bloomstate.texture_bloom = NULL;
4260 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4261 r_bloomstate.bloomtextureheight = bloomtextureheight;
4262 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4263 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);
4266 // when doing a reduced render (HDR) we want to use a smaller area
4267 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4268 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4269 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4270 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4271 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4273 // set up a texcoord array for the full resolution screen image
4274 // (we have to keep this around to copy back during final render)
4275 r_bloomstate.screentexcoord2f[0] = 0;
4276 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4277 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4278 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4279 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4280 r_bloomstate.screentexcoord2f[5] = 0;
4281 r_bloomstate.screentexcoord2f[6] = 0;
4282 r_bloomstate.screentexcoord2f[7] = 0;
4284 // set up a texcoord array for the reduced resolution bloom image
4285 // (which will be additive blended over the screen image)
4286 r_bloomstate.bloomtexcoord2f[0] = 0;
4287 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4288 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4289 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4290 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4291 r_bloomstate.bloomtexcoord2f[5] = 0;
4292 r_bloomstate.bloomtexcoord2f[6] = 0;
4293 r_bloomstate.bloomtexcoord2f[7] = 0;
4295 if (r_hdr.integer || r_bloom.integer)
4297 r_bloomstate.enabled = true;
4298 r_bloomstate.hdr = r_hdr.integer != 0;
4301 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);
4304 void R_Bloom_CopyBloomTexture(float colorscale)
4306 r_refdef.stats.bloom++;
4308 // scale down screen texture to the bloom texture size
4310 R_SetViewport(&r_bloomstate.viewport);
4311 GL_BlendFunc(GL_ONE, GL_ZERO);
4312 GL_Color(colorscale, colorscale, colorscale, 1);
4313 // TODO: optimize with multitexture or GLSL
4314 R_SetupGenericShader(true);
4315 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4316 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4317 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4318 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4320 // we now have a bloom image in the framebuffer
4321 // copy it into the bloom image texture for later processing
4322 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4323 GL_ActiveTexture(0);
4325 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4326 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4329 void R_Bloom_CopyHDRTexture(void)
4331 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4332 GL_ActiveTexture(0);
4334 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
4335 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4338 void R_Bloom_MakeTexture(void)
4341 float xoffset, yoffset, r, brighten;
4343 r_refdef.stats.bloom++;
4345 R_ResetViewRendering2D();
4346 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4347 R_Mesh_ColorPointer(NULL, 0, 0);
4348 R_SetupGenericShader(true);
4350 // we have a bloom image in the framebuffer
4352 R_SetViewport(&r_bloomstate.viewport);
4354 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4357 r = bound(0, r_bloom_colorexponent.value / x, 1);
4358 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4359 GL_Color(r, r, r, 1);
4360 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4361 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4362 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4363 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4365 // copy the vertically blurred bloom view to a texture
4366 GL_ActiveTexture(0);
4368 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4369 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4372 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4373 brighten = r_bloom_brighten.value;
4375 brighten *= r_hdr_range.value;
4376 brighten = sqrt(brighten);
4378 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4379 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4380 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4382 for (dir = 0;dir < 2;dir++)
4384 // blend on at multiple vertical offsets to achieve a vertical blur
4385 // TODO: do offset blends using GLSL
4386 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4387 GL_BlendFunc(GL_ONE, GL_ZERO);
4388 for (x = -range;x <= range;x++)
4390 if (!dir){xoffset = 0;yoffset = x;}
4391 else {xoffset = x;yoffset = 0;}
4392 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4393 yoffset /= (float)r_bloomstate.bloomtextureheight;
4394 // compute a texcoord array with the specified x and y offset
4395 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4396 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4397 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4398 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4399 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4400 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4401 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4402 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4403 // this r value looks like a 'dot' particle, fading sharply to
4404 // black at the edges
4405 // (probably not realistic but looks good enough)
4406 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4407 //r = brighten/(range*2+1);
4408 r = brighten / (range * 2 + 1);
4410 r *= (1 - x*x/(float)(range*range));
4411 GL_Color(r, r, r, 1);
4412 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4413 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4414 GL_BlendFunc(GL_ONE, GL_ONE);
4417 // copy the vertically blurred bloom view to a texture
4418 GL_ActiveTexture(0);
4420 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4421 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4424 // apply subtract last
4425 // (just like it would be in a GLSL shader)
4426 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4428 GL_BlendFunc(GL_ONE, GL_ZERO);
4429 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4430 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4431 GL_Color(1, 1, 1, 1);
4432 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4433 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4435 GL_BlendFunc(GL_ONE, GL_ONE);
4436 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4437 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4438 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4439 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4440 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4441 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4442 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4444 // copy the darkened bloom view to a texture
4445 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4446 GL_ActiveTexture(0);
4448 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4449 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4453 void R_HDR_RenderBloomTexture(void)
4455 int oldwidth, oldheight;
4456 float oldcolorscale;
4458 oldcolorscale = r_refdef.view.colorscale;
4459 oldwidth = r_refdef.view.width;
4460 oldheight = r_refdef.view.height;
4461 r_refdef.view.width = r_bloomstate.bloomwidth;
4462 r_refdef.view.height = r_bloomstate.bloomheight;
4464 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4465 // TODO: add exposure compensation features
4466 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4468 r_refdef.view.showdebug = false;
4469 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4471 R_ResetViewRendering3D();
4473 R_ClearScreen(r_refdef.fogenabled);
4474 if (r_timereport_active)
4475 R_TimeReport("HDRclear");
4478 if (r_timereport_active)
4479 R_TimeReport("visibility");
4481 // only do secondary renders with HDR if r_hdr is 2 or higher
4482 r_waterstate.numwaterplanes = 0;
4483 if (r_waterstate.enabled && r_hdr.integer >= 2)
4484 R_RenderWaterPlanes();
4486 r_refdef.view.showdebug = true;
4488 r_waterstate.numwaterplanes = 0;
4490 R_ResetViewRendering2D();
4492 R_Bloom_CopyHDRTexture();
4493 R_Bloom_MakeTexture();
4495 // restore the view settings
4496 r_refdef.view.width = oldwidth;
4497 r_refdef.view.height = oldheight;
4498 r_refdef.view.colorscale = oldcolorscale;
4500 R_ResetViewRendering3D();
4502 R_ClearScreen(r_refdef.fogenabled);
4503 if (r_timereport_active)
4504 R_TimeReport("viewclear");
4507 static void R_BlendView(void)
4509 if (r_bloomstate.texture_screen)
4511 // make sure the buffer is available
4512 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4514 R_ResetViewRendering2D();
4515 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4516 R_Mesh_ColorPointer(NULL, 0, 0);
4517 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4518 GL_ActiveTexture(0);CHECKGLERROR
4520 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4522 // declare variables
4524 static float avgspeed;
4526 speed = VectorLength(cl.movement_velocity);
4528 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4529 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4531 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4532 speed = bound(0, speed, 1);
4533 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4535 // calculate values into a standard alpha
4536 cl.motionbluralpha = 1 - exp(-
4538 (r_motionblur.value * speed / 80)
4540 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4543 max(0.0001, cl.time - cl.oldtime) // fps independent
4546 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4547 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4549 if (cl.motionbluralpha > 0)
4551 R_SetupGenericShader(true);
4552 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4553 GL_Color(1, 1, 1, cl.motionbluralpha);
4554 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4555 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4556 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4557 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4561 // copy view into the screen texture
4562 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4563 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4566 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4568 unsigned int permutation =
4569 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4570 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4571 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4572 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4573 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4575 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4577 // render simple bloom effect
4578 // copy the screen and shrink it and darken it for the bloom process
4579 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4580 // make the bloom texture
4581 R_Bloom_MakeTexture();
4584 R_ResetViewRendering2D();
4585 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4586 R_Mesh_ColorPointer(NULL, 0, 0);
4587 GL_Color(1, 1, 1, 1);
4588 GL_BlendFunc(GL_ONE, GL_ZERO);
4589 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4590 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4591 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4592 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4593 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4594 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4595 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4596 if (r_glsl_permutation->loc_TintColor >= 0)
4597 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4598 if (r_glsl_permutation->loc_ClientTime >= 0)
4599 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4600 if (r_glsl_permutation->loc_PixelSize >= 0)
4601 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4602 if (r_glsl_permutation->loc_UserVec1 >= 0)
4604 float a=0, b=0, c=0, d=0;
4605 #if _MSC_VER >= 1400
4606 #define sscanf sscanf_s
4608 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4609 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4611 if (r_glsl_permutation->loc_UserVec2 >= 0)
4613 float a=0, b=0, c=0, d=0;
4614 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4615 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4617 if (r_glsl_permutation->loc_UserVec3 >= 0)
4619 float a=0, b=0, c=0, d=0;
4620 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4621 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4623 if (r_glsl_permutation->loc_UserVec4 >= 0)
4625 float a=0, b=0, c=0, d=0;
4626 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4627 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4629 if (r_glsl_permutation->loc_Saturation >= 0)
4630 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4631 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4632 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4638 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4640 // render high dynamic range bloom effect
4641 // the bloom texture was made earlier this render, so we just need to
4642 // blend it onto the screen...
4643 R_ResetViewRendering2D();
4644 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4645 R_Mesh_ColorPointer(NULL, 0, 0);
4646 R_SetupGenericShader(true);
4647 GL_Color(1, 1, 1, 1);
4648 GL_BlendFunc(GL_ONE, GL_ONE);
4649 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4650 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4651 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4652 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4654 else if (r_bloomstate.texture_bloom)
4656 // render simple bloom effect
4657 // copy the screen and shrink it and darken it for the bloom process
4658 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4659 // make the bloom texture
4660 R_Bloom_MakeTexture();
4661 // put the original screen image back in place and blend the bloom
4663 R_ResetViewRendering2D();
4664 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4665 R_Mesh_ColorPointer(NULL, 0, 0);
4666 GL_Color(1, 1, 1, 1);
4667 GL_BlendFunc(GL_ONE, GL_ZERO);
4668 // do both in one pass if possible
4669 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4670 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4671 if (r_textureunits.integer >= 2 && gl_combine.integer)
4673 R_SetupGenericTwoTextureShader(GL_ADD);
4674 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4675 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4679 R_SetupGenericShader(true);
4680 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4681 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4682 // now blend on the bloom texture
4683 GL_BlendFunc(GL_ONE, GL_ONE);
4684 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4685 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4687 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4688 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4690 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4692 // apply a color tint to the whole view
4693 R_ResetViewRendering2D();
4694 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4695 R_Mesh_ColorPointer(NULL, 0, 0);
4696 R_SetupGenericShader(false);
4697 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4698 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4699 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4703 matrix4x4_t r_waterscrollmatrix;
4705 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4707 if (r_refdef.fog_density)
4709 r_refdef.fogcolor[0] = r_refdef.fog_red;
4710 r_refdef.fogcolor[1] = r_refdef.fog_green;
4711 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4713 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4714 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4715 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4716 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4720 VectorCopy(r_refdef.fogcolor, fogvec);
4721 // color.rgb *= ContrastBoost * SceneBrightness;
4722 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4723 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4724 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4725 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4730 void R_UpdateVariables(void)
4734 r_refdef.scene.ambient = r_ambient.value;
4736 r_refdef.farclip = r_farclip_base.value;
4737 if (r_refdef.scene.worldmodel)
4738 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
4739 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4741 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4742 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4743 r_refdef.polygonfactor = 0;
4744 r_refdef.polygonoffset = 0;
4745 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4746 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4748 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4749 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4750 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4751 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4752 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4753 if (r_showsurfaces.integer)
4755 r_refdef.scene.rtworld = false;
4756 r_refdef.scene.rtworldshadows = false;
4757 r_refdef.scene.rtdlight = false;
4758 r_refdef.scene.rtdlightshadows = false;
4759 r_refdef.lightmapintensity = 0;
4762 if (gamemode == GAME_NEHAHRA)
4764 if (gl_fogenable.integer)
4766 r_refdef.oldgl_fogenable = true;
4767 r_refdef.fog_density = gl_fogdensity.value;
4768 r_refdef.fog_red = gl_fogred.value;
4769 r_refdef.fog_green = gl_foggreen.value;
4770 r_refdef.fog_blue = gl_fogblue.value;
4771 r_refdef.fog_alpha = 1;
4772 r_refdef.fog_start = 0;
4773 r_refdef.fog_end = gl_skyclip.value;
4774 r_refdef.fog_height = 1<<30;
4775 r_refdef.fog_fadedepth = 128;
4777 else if (r_refdef.oldgl_fogenable)
4779 r_refdef.oldgl_fogenable = false;
4780 r_refdef.fog_density = 0;
4781 r_refdef.fog_red = 0;
4782 r_refdef.fog_green = 0;
4783 r_refdef.fog_blue = 0;
4784 r_refdef.fog_alpha = 0;
4785 r_refdef.fog_start = 0;
4786 r_refdef.fog_end = 0;
4787 r_refdef.fog_height = 1<<30;
4788 r_refdef.fog_fadedepth = 128;
4792 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4793 r_refdef.fog_start = max(0, r_refdef.fog_start);
4794 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4796 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4798 if (r_refdef.fog_density && r_drawfog.integer)
4800 r_refdef.fogenabled = true;
4801 // this is the point where the fog reaches 0.9986 alpha, which we
4802 // consider a good enough cutoff point for the texture
4803 // (0.9986 * 256 == 255.6)
4804 if (r_fog_exp2.integer)
4805 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4807 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4808 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4809 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4810 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4811 // fog color was already set
4812 // update the fog texture
4813 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)
4814 R_BuildFogTexture();
4817 r_refdef.fogenabled = false;
4819 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4821 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4823 // build GLSL gamma texture
4824 #define RAMPWIDTH 256
4825 unsigned short ramp[RAMPWIDTH * 3];
4826 unsigned char rampbgr[RAMPWIDTH][4];
4829 r_texture_gammaramps_serial = vid_gammatables_serial;
4831 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4832 for(i = 0; i < RAMPWIDTH; ++i)
4834 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4835 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4836 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4839 if (r_texture_gammaramps)
4841 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4845 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);
4851 // remove GLSL gamma texture
4855 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4856 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4862 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4863 if( scenetype != r_currentscenetype ) {
4864 // store the old scenetype
4865 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4866 r_currentscenetype = scenetype;
4867 // move in the new scene
4868 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4877 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4879 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4880 if( scenetype == r_currentscenetype ) {
4881 return &r_refdef.scene;
4883 return &r_scenes_store[ scenetype ];
4892 void R_RenderView(void)
4894 if (r_timereport_active)
4895 R_TimeReport("start");
4896 r_frame++; // used only by R_GetCurrentTexture
4897 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4899 R_AnimCache_NewFrame();
4901 if (r_refdef.view.isoverlay)
4903 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4904 GL_Clear( GL_DEPTH_BUFFER_BIT );
4905 R_TimeReport("depthclear");
4907 r_refdef.view.showdebug = false;
4909 r_waterstate.enabled = false;
4910 r_waterstate.numwaterplanes = 0;
4918 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4919 return; //Host_Error ("R_RenderView: NULL worldmodel");
4921 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4923 // break apart the view matrix into vectors for various purposes
4924 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4925 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4926 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4927 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4928 // make an inverted copy of the view matrix for tracking sprites
4929 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4931 R_Shadow_UpdateWorldLightSelection();
4933 R_Bloom_StartFrame();
4934 R_Water_StartFrame();
4937 if (r_timereport_active)
4938 R_TimeReport("viewsetup");
4940 R_ResetViewRendering3D();
4942 if (r_refdef.view.clear || r_refdef.fogenabled)
4944 R_ClearScreen(r_refdef.fogenabled);
4945 if (r_timereport_active)
4946 R_TimeReport("viewclear");
4948 r_refdef.view.clear = true;
4950 // this produces a bloom texture to be used in R_BlendView() later
4952 R_HDR_RenderBloomTexture();
4954 r_refdef.view.showdebug = true;
4957 if (r_timereport_active)
4958 R_TimeReport("visibility");
4960 r_waterstate.numwaterplanes = 0;
4961 if (r_waterstate.enabled)
4962 R_RenderWaterPlanes();
4965 r_waterstate.numwaterplanes = 0;
4968 if (r_timereport_active)
4969 R_TimeReport("blendview");
4971 GL_Scissor(0, 0, vid.width, vid.height);
4972 GL_ScissorTest(false);
4976 void R_RenderWaterPlanes(void)
4978 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4980 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4981 if (r_timereport_active)
4982 R_TimeReport("waterworld");
4985 // don't let sound skip if going slow
4986 if (r_refdef.scene.extraupdate)
4989 R_DrawModelsAddWaterPlanes();
4990 if (r_timereport_active)
4991 R_TimeReport("watermodels");
4993 if (r_waterstate.numwaterplanes)
4995 R_Water_ProcessPlanes();
4996 if (r_timereport_active)
4997 R_TimeReport("waterscenes");
5001 extern void R_DrawLightningBeams (void);
5002 extern void VM_CL_AddPolygonsToMeshQueue (void);
5003 extern void R_DrawPortals (void);
5004 extern cvar_t cl_locs_show;
5005 static void R_DrawLocs(void);
5006 static void R_DrawEntityBBoxes(void);
5007 static void R_DrawModelDecals(void);
5008 extern cvar_t cl_decals_newsystem;
5009 void R_RenderScene(void)
5011 r_refdef.stats.renders++;
5015 // don't let sound skip if going slow
5016 if (r_refdef.scene.extraupdate)
5019 R_MeshQueue_BeginScene();
5023 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);
5025 if (cl.csqc_vidvars.drawworld)
5027 // don't let sound skip if going slow
5028 if (r_refdef.scene.extraupdate)
5031 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5033 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5034 if (r_timereport_active)
5035 R_TimeReport("worldsky");
5038 if (R_DrawBrushModelsSky() && r_timereport_active)
5039 R_TimeReport("bmodelsky");
5041 if (skyrendermasked && skyrenderlater)
5043 // we have to force off the water clipping plane while rendering sky
5050 R_AnimCache_CacheVisibleEntities();
5052 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5054 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5055 if (r_timereport_active)
5056 R_TimeReport("worlddepth");
5058 if (r_depthfirst.integer >= 2)
5060 R_DrawModelsDepth();
5061 if (r_timereport_active)
5062 R_TimeReport("modeldepth");
5065 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5067 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5068 if (r_timereport_active)
5069 R_TimeReport("world");
5072 // don't let sound skip if going slow
5073 if (r_refdef.scene.extraupdate)
5077 if (r_timereport_active)
5078 R_TimeReport("models");
5080 // don't let sound skip if going slow
5081 if (r_refdef.scene.extraupdate)
5084 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5086 R_DrawModelShadows();
5087 R_ResetViewRendering3D();
5088 // don't let sound skip if going slow
5089 if (r_refdef.scene.extraupdate)
5093 R_ShadowVolumeLighting(false);
5094 if (r_timereport_active)
5095 R_TimeReport("rtlights");
5097 // don't let sound skip if going slow
5098 if (r_refdef.scene.extraupdate)
5101 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5103 R_DrawModelShadows();
5104 R_ResetViewRendering3D();
5105 // don't let sound skip if going slow
5106 if (r_refdef.scene.extraupdate)
5110 if (cl.csqc_vidvars.drawworld)
5112 if (cl_decals_newsystem.integer)
5114 R_DrawModelDecals();
5115 if (r_timereport_active)
5116 R_TimeReport("modeldecals");
5121 if (r_timereport_active)
5122 R_TimeReport("decals");
5126 if (r_timereport_active)
5127 R_TimeReport("particles");
5130 if (r_timereport_active)
5131 R_TimeReport("explosions");
5133 R_DrawLightningBeams();
5134 if (r_timereport_active)
5135 R_TimeReport("lightning");
5138 R_SetupGenericShader(true);
5139 VM_CL_AddPolygonsToMeshQueue();
5141 if (r_refdef.view.showdebug)
5143 if (cl_locs_show.integer)
5146 if (r_timereport_active)
5147 R_TimeReport("showlocs");
5150 if (r_drawportals.integer)
5153 if (r_timereport_active)
5154 R_TimeReport("portals");
5157 if (r_showbboxes.value > 0)
5159 R_DrawEntityBBoxes();
5160 if (r_timereport_active)
5161 R_TimeReport("bboxes");
5165 R_SetupGenericShader(true);
5166 R_MeshQueue_RenderTransparent();
5167 if (r_timereport_active)
5168 R_TimeReport("drawtrans");
5170 R_SetupGenericShader(true);
5172 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))
5174 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5175 if (r_timereport_active)
5176 R_TimeReport("worlddebug");
5177 R_DrawModelsDebug();
5178 if (r_timereport_active)
5179 R_TimeReport("modeldebug");
5182 R_SetupGenericShader(true);
5184 if (cl.csqc_vidvars.drawworld)
5187 if (r_timereport_active)
5188 R_TimeReport("coronas");
5191 // don't let sound skip if going slow
5192 if (r_refdef.scene.extraupdate)
5195 R_ResetViewRendering2D();
5198 static const unsigned short bboxelements[36] =
5208 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5211 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5213 RSurf_ActiveWorldEntity();
5215 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5216 GL_DepthMask(false);
5217 GL_DepthRange(0, 1);
5218 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5219 R_Mesh_ResetTextureState();
5221 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5222 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5223 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5224 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5225 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5226 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5227 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5228 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5229 R_FillColors(color4f, 8, cr, cg, cb, ca);
5230 if (r_refdef.fogenabled)
5232 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5234 f1 = RSurf_FogVertex(v);
5236 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5237 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5238 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5241 R_Mesh_VertexPointer(vertex3f, 0, 0);
5242 R_Mesh_ColorPointer(color4f, 0, 0);
5243 R_Mesh_ResetTextureState();
5244 R_SetupGenericShader(false);
5245 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5248 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5252 prvm_edict_t *edict;
5253 prvm_prog_t *prog_save = prog;
5255 // this function draws bounding boxes of server entities
5259 GL_CullFace(GL_NONE);
5260 R_SetupGenericShader(false);
5264 for (i = 0;i < numsurfaces;i++)
5266 edict = PRVM_EDICT_NUM(surfacelist[i]);
5267 switch ((int)edict->fields.server->solid)
5269 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5270 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5271 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5272 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5273 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5274 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5276 color[3] *= r_showbboxes.value;
5277 color[3] = bound(0, color[3], 1);
5278 GL_DepthTest(!r_showdisabledepthtest.integer);
5279 GL_CullFace(r_refdef.view.cullface_front);
5280 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5286 static void R_DrawEntityBBoxes(void)
5289 prvm_edict_t *edict;
5291 prvm_prog_t *prog_save = prog;
5293 // this function draws bounding boxes of server entities
5299 for (i = 0;i < prog->num_edicts;i++)
5301 edict = PRVM_EDICT_NUM(i);
5302 if (edict->priv.server->free)
5304 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5305 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5307 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5309 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5310 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5316 static const int nomodelelement3i[24] =
5328 static const unsigned short nomodelelement3s[24] =
5340 static const float nomodelvertex3f[6*3] =
5350 static const float nomodelcolor4f[6*4] =
5352 0.0f, 0.0f, 0.5f, 1.0f,
5353 0.0f, 0.0f, 0.5f, 1.0f,
5354 0.0f, 0.5f, 0.0f, 1.0f,
5355 0.0f, 0.5f, 0.0f, 1.0f,
5356 0.5f, 0.0f, 0.0f, 1.0f,
5357 0.5f, 0.0f, 0.0f, 1.0f
5360 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5366 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);
5368 // this is only called once per entity so numsurfaces is always 1, and
5369 // surfacelist is always {0}, so this code does not handle batches
5371 if (rsurface.ent_flags & RENDER_ADDITIVE)
5373 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5374 GL_DepthMask(false);
5376 else if (rsurface.ent_color[3] < 1)
5378 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5379 GL_DepthMask(false);
5383 GL_BlendFunc(GL_ONE, GL_ZERO);
5386 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5387 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5388 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5389 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5390 R_SetupGenericShader(false);
5391 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5392 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5393 R_Mesh_ColorPointer(color4f, 0, 0);
5394 for (i = 0, c = color4f;i < 6;i++, c += 4)
5396 c[0] *= rsurface.ent_color[0];
5397 c[1] *= rsurface.ent_color[1];
5398 c[2] *= rsurface.ent_color[2];
5399 c[3] *= rsurface.ent_color[3];
5401 if (r_refdef.fogenabled)
5403 for (i = 0, c = color4f;i < 6;i++, c += 4)
5405 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5407 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5408 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5409 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5412 R_Mesh_ResetTextureState();
5413 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5416 void R_DrawNoModel(entity_render_t *ent)
5419 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5420 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5421 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5423 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5426 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5428 vec3_t right1, right2, diff, normal;
5430 VectorSubtract (org2, org1, normal);
5432 // calculate 'right' vector for start
5433 VectorSubtract (r_refdef.view.origin, org1, diff);
5434 CrossProduct (normal, diff, right1);
5435 VectorNormalize (right1);
5437 // calculate 'right' vector for end
5438 VectorSubtract (r_refdef.view.origin, org2, diff);
5439 CrossProduct (normal, diff, right2);
5440 VectorNormalize (right2);
5442 vert[ 0] = org1[0] + width * right1[0];
5443 vert[ 1] = org1[1] + width * right1[1];
5444 vert[ 2] = org1[2] + width * right1[2];
5445 vert[ 3] = org1[0] - width * right1[0];
5446 vert[ 4] = org1[1] - width * right1[1];
5447 vert[ 5] = org1[2] - width * right1[2];
5448 vert[ 6] = org2[0] - width * right2[0];
5449 vert[ 7] = org2[1] - width * right2[1];
5450 vert[ 8] = org2[2] - width * right2[2];
5451 vert[ 9] = org2[0] + width * right2[0];
5452 vert[10] = org2[1] + width * right2[1];
5453 vert[11] = org2[2] + width * right2[2];
5456 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)
5458 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5459 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5460 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5461 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5462 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5463 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5464 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5465 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5466 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5467 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5468 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5469 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5472 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5477 VectorSet(v, x, y, z);
5478 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5479 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5481 if (i == mesh->numvertices)
5483 if (mesh->numvertices < mesh->maxvertices)
5485 VectorCopy(v, vertex3f);
5486 mesh->numvertices++;
5488 return mesh->numvertices;
5494 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5498 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5499 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5500 e = mesh->element3i + mesh->numtriangles * 3;
5501 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5503 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5504 if (mesh->numtriangles < mesh->maxtriangles)
5509 mesh->numtriangles++;
5511 element[1] = element[2];
5515 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5519 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5520 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5521 e = mesh->element3i + mesh->numtriangles * 3;
5522 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5524 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5525 if (mesh->numtriangles < mesh->maxtriangles)
5530 mesh->numtriangles++;
5532 element[1] = element[2];
5536 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5537 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5539 int planenum, planenum2;
5542 mplane_t *plane, *plane2;
5544 double temppoints[2][256*3];
5545 // figure out how large a bounding box we need to properly compute this brush
5547 for (w = 0;w < numplanes;w++)
5548 maxdist = max(maxdist, fabs(planes[w].dist));
5549 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5550 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5551 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5555 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5556 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5558 if (planenum2 == planenum)
5560 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);
5563 if (tempnumpoints < 3)
5565 // generate elements forming a triangle fan for this polygon
5566 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5570 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)
5572 texturelayer_t *layer;
5573 layer = t->currentlayers + t->currentnumlayers++;
5575 layer->depthmask = depthmask;
5576 layer->blendfunc1 = blendfunc1;
5577 layer->blendfunc2 = blendfunc2;
5578 layer->texture = texture;
5579 layer->texmatrix = *matrix;
5580 layer->color[0] = r * r_refdef.view.colorscale;
5581 layer->color[1] = g * r_refdef.view.colorscale;
5582 layer->color[2] = b * r_refdef.view.colorscale;
5583 layer->color[3] = a;
5586 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5589 index = parms[2] + r_refdef.scene.time * parms[3];
5590 index -= floor(index);
5594 case Q3WAVEFUNC_NONE:
5595 case Q3WAVEFUNC_NOISE:
5596 case Q3WAVEFUNC_COUNT:
5599 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5600 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5601 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5602 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5603 case Q3WAVEFUNC_TRIANGLE:
5605 f = index - floor(index);
5616 return (float)(parms[0] + parms[1] * f);
5619 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5624 matrix4x4_t matrix, temp;
5625 switch(tcmod->tcmod)
5629 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5630 matrix = r_waterscrollmatrix;
5632 matrix = identitymatrix;
5634 case Q3TCMOD_ENTITYTRANSLATE:
5635 // this is used in Q3 to allow the gamecode to control texcoord
5636 // scrolling on the entity, which is not supported in darkplaces yet.
5637 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5639 case Q3TCMOD_ROTATE:
5640 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5641 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5642 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5645 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5647 case Q3TCMOD_SCROLL:
5648 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5650 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5651 w = (int) tcmod->parms[0];
5652 h = (int) tcmod->parms[1];
5653 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5655 idx = (int) floor(f * w * h);
5656 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5658 case Q3TCMOD_STRETCH:
5659 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5660 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5662 case Q3TCMOD_TRANSFORM:
5663 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5664 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5665 VectorSet(tcmat + 6, 0 , 0 , 1);
5666 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5667 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5669 case Q3TCMOD_TURBULENT:
5670 // this is handled in the RSurf_PrepareVertices function
5671 matrix = identitymatrix;
5675 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5678 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5680 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5681 char name[MAX_QPATH];
5682 skinframe_t *skinframe;
5683 unsigned char pixels[296*194];
5684 strlcpy(cache->name, skinname, sizeof(cache->name));
5685 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5686 if (developer_loading.integer)
5687 Con_Printf("loading %s\n", name);
5688 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5689 if (!skinframe || !skinframe->base)
5692 fs_offset_t filesize;
5694 f = FS_LoadFile(name, tempmempool, true, &filesize);
5697 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5698 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5702 cache->skinframe = skinframe;
5705 texture_t *R_GetCurrentTexture(texture_t *t)
5708 const entity_render_t *ent = rsurface.entity;
5709 dp_model_t *model = ent->model;
5710 q3shaderinfo_layer_tcmod_t *tcmod;
5712 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5713 return t->currentframe;
5714 t->update_lastrenderframe = r_frame;
5715 t->update_lastrenderentity = (void *)ent;
5717 // switch to an alternate material if this is a q1bsp animated material
5719 texture_t *texture = t;
5720 int s = rsurface.ent_skinnum;
5721 if ((unsigned int)s >= (unsigned int)model->numskins)
5723 if (model->skinscenes)
5725 if (model->skinscenes[s].framecount > 1)
5726 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5728 s = model->skinscenes[s].firstframe;
5731 t = t + s * model->num_surfaces;
5734 // use an alternate animation if the entity's frame is not 0,
5735 // and only if the texture has an alternate animation
5736 if (rsurface.ent_alttextures && t->anim_total[1])
5737 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5739 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5741 texture->currentframe = t;
5744 // update currentskinframe to be a qw skin or animation frame
5745 if (rsurface.ent_qwskin >= 0)
5747 i = rsurface.ent_qwskin;
5748 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5750 r_qwskincache_size = cl.maxclients;
5752 Mem_Free(r_qwskincache);
5753 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5755 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5756 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5757 t->currentskinframe = r_qwskincache[i].skinframe;
5758 if (t->currentskinframe == NULL)
5759 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5761 else if (t->numskinframes >= 2)
5762 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5763 if (t->backgroundnumskinframes >= 2)
5764 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5766 t->currentmaterialflags = t->basematerialflags;
5767 t->currentalpha = rsurface.ent_color[3];
5768 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5769 t->currentalpha *= r_wateralpha.value;
5770 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5771 t->currentalpha *= t->r_water_wateralpha;
5772 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5773 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5774 if (!(rsurface.ent_flags & RENDER_LIGHT))
5775 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5776 else if (rsurface.modeltexcoordlightmap2f == NULL)
5778 // pick a model lighting mode
5779 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5780 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5782 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5784 if (rsurface.ent_flags & RENDER_ADDITIVE)
5785 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5786 else if (t->currentalpha < 1)
5787 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5788 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5789 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5790 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5791 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5792 if (t->backgroundnumskinframes)
5793 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5794 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5796 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5797 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5800 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5802 // there is no tcmod
5803 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5805 t->currenttexmatrix = r_waterscrollmatrix;
5806 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5808 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
5810 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5811 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5814 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5815 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5816 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5817 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5819 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5820 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5821 t->glosstexture = r_texture_black;
5822 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5823 t->backgroundglosstexture = r_texture_black;
5824 t->specularpower = r_shadow_glossexponent.value;
5825 // TODO: store reference values for these in the texture?
5826 t->specularscale = 0;
5827 if (r_shadow_gloss.integer > 0)
5829 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5831 if (r_shadow_glossintensity.value > 0)
5833 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5834 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5835 t->specularscale = r_shadow_glossintensity.value;
5838 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5840 t->glosstexture = r_texture_white;
5841 t->backgroundglosstexture = r_texture_white;
5842 t->specularscale = r_shadow_gloss2intensity.value;
5843 t->specularpower = r_shadow_gloss2exponent.value;
5846 t->specularscale *= t->specularscalemod;
5847 t->specularpower *= t->specularpowermod;
5849 // lightmaps mode looks bad with dlights using actual texturing, so turn
5850 // off the colormap and glossmap, but leave the normalmap on as it still
5851 // accurately represents the shading involved
5852 if (gl_lightmaps.integer)
5854 t->basetexture = r_texture_grey128;
5855 t->backgroundbasetexture = NULL;
5856 t->specularscale = 0;
5857 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5860 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5861 VectorClear(t->dlightcolor);
5862 t->currentnumlayers = 0;
5863 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5866 int blendfunc1, blendfunc2;
5868 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5870 blendfunc1 = GL_SRC_ALPHA;
5871 blendfunc2 = GL_ONE;
5873 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5875 blendfunc1 = GL_SRC_ALPHA;
5876 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5878 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5880 blendfunc1 = t->customblendfunc[0];
5881 blendfunc2 = t->customblendfunc[1];
5885 blendfunc1 = GL_ONE;
5886 blendfunc2 = GL_ZERO;
5888 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5889 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5890 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5891 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5893 // fullbright is not affected by r_refdef.lightmapintensity
5894 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]);
5895 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5896 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]);
5897 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5898 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]);
5902 vec3_t ambientcolor;
5904 // set the color tint used for lights affecting this surface
5905 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5907 // q3bsp has no lightmap updates, so the lightstylevalue that
5908 // would normally be baked into the lightmap must be
5909 // applied to the color
5910 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5911 if (model->type == mod_brushq3)
5912 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5913 colorscale *= r_refdef.lightmapintensity;
5914 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5915 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5916 // basic lit geometry
5917 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]);
5918 // add pants/shirt if needed
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_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]);
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_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]);
5923 // now add ambient passes if needed
5924 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5926 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]);
5927 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5928 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]);
5929 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5930 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]);
5933 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5934 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]);
5935 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5937 // if this is opaque use alpha blend which will darken the earlier
5940 // if this is an alpha blended material, all the earlier passes
5941 // were darkened by fog already, so we only need to add the fog
5942 // color ontop through the fog mask texture
5944 // if this is an additive blended material, all the earlier passes
5945 // were darkened by fog already, and we should not add fog color
5946 // (because the background was not darkened, there is no fog color
5947 // that was lost behind it).
5948 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]);
5952 return t->currentframe;
5955 rsurfacestate_t rsurface;
5957 void R_Mesh_ResizeArrays(int newvertices)
5960 if (rsurface.array_size >= newvertices)
5962 if (rsurface.array_modelvertex3f)
5963 Mem_Free(rsurface.array_modelvertex3f);
5964 rsurface.array_size = (newvertices + 1023) & ~1023;
5965 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5966 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5967 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5968 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5969 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5970 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5971 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5972 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5973 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5974 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5975 rsurface.array_color4f = base + rsurface.array_size * 27;
5976 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5979 void RSurf_ActiveWorldEntity(void)
5981 dp_model_t *model = r_refdef.scene.worldmodel;
5982 //if (rsurface.entity == r_refdef.scene.worldentity)
5984 rsurface.entity = r_refdef.scene.worldentity;
5985 rsurface.skeleton = NULL;
5986 rsurface.ent_skinnum = 0;
5987 rsurface.ent_qwskin = -1;
5988 rsurface.ent_shadertime = 0;
5989 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
5990 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
5991 if (rsurface.array_size < model->surfmesh.num_vertices)
5992 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5993 rsurface.matrix = identitymatrix;
5994 rsurface.inversematrix = identitymatrix;
5995 rsurface.matrixscale = 1;
5996 rsurface.inversematrixscale = 1;
5997 R_Mesh_Matrix(&identitymatrix);
5998 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5999 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6000 rsurface.fograngerecip = r_refdef.fograngerecip;
6001 rsurface.fogheightfade = r_refdef.fogheightfade;
6002 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6003 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6004 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6005 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6006 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6007 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6008 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6009 VectorSet(rsurface.glowmod, 1, 1, 1);
6010 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6011 rsurface.frameblend[0].lerp = 1;
6012 rsurface.ent_alttextures = false;
6013 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6014 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6015 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6016 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6017 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6018 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6019 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6020 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6021 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6022 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6023 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6024 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6025 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6026 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6027 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6028 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6029 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6030 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6031 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6032 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6033 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6034 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6035 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6036 rsurface.modelelement3i = model->surfmesh.data_element3i;
6037 rsurface.modelelement3s = model->surfmesh.data_element3s;
6038 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6039 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6040 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6041 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6042 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6043 rsurface.modelsurfaces = model->data_surfaces;
6044 rsurface.generatedvertex = false;
6045 rsurface.vertex3f = rsurface.modelvertex3f;
6046 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6047 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6048 rsurface.svector3f = rsurface.modelsvector3f;
6049 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6050 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6051 rsurface.tvector3f = rsurface.modeltvector3f;
6052 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6053 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6054 rsurface.normal3f = rsurface.modelnormal3f;
6055 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6056 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6057 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6060 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6062 dp_model_t *model = ent->model;
6063 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6065 rsurface.entity = (entity_render_t *)ent;
6066 rsurface.skeleton = ent->skeleton;
6067 rsurface.ent_skinnum = ent->skinnum;
6068 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;
6069 rsurface.ent_shadertime = ent->shadertime;
6070 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6071 rsurface.ent_flags = ent->flags;
6072 if (rsurface.array_size < model->surfmesh.num_vertices)
6073 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6074 rsurface.matrix = ent->matrix;
6075 rsurface.inversematrix = ent->inversematrix;
6076 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6077 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6078 R_Mesh_Matrix(&rsurface.matrix);
6079 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6080 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6081 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6082 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6083 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6084 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6085 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6086 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6087 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6088 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6089 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6090 VectorCopy(ent->glowmod, rsurface.glowmod);
6091 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6092 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6093 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6094 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6095 if (ent->model->brush.submodel)
6097 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6098 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6100 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6102 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6104 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6105 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6106 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6107 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6109 else if (wanttangents)
6111 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6112 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6113 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6114 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6115 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6117 else if (wantnormals)
6119 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6120 rsurface.modelsvector3f = NULL;
6121 rsurface.modeltvector3f = NULL;
6122 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6123 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6127 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6128 rsurface.modelsvector3f = NULL;
6129 rsurface.modeltvector3f = NULL;
6130 rsurface.modelnormal3f = NULL;
6131 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6133 rsurface.modelvertex3f_bufferobject = 0;
6134 rsurface.modelvertex3f_bufferoffset = 0;
6135 rsurface.modelsvector3f_bufferobject = 0;
6136 rsurface.modelsvector3f_bufferoffset = 0;
6137 rsurface.modeltvector3f_bufferobject = 0;
6138 rsurface.modeltvector3f_bufferoffset = 0;
6139 rsurface.modelnormal3f_bufferobject = 0;
6140 rsurface.modelnormal3f_bufferoffset = 0;
6141 rsurface.generatedvertex = true;
6145 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6146 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6147 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6148 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6149 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6150 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6151 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6152 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6153 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6154 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6155 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6156 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6157 rsurface.generatedvertex = false;
6159 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6160 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6161 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6162 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6163 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6164 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6165 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6166 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6167 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6168 rsurface.modelelement3i = model->surfmesh.data_element3i;
6169 rsurface.modelelement3s = model->surfmesh.data_element3s;
6170 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6171 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6172 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6173 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6174 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6175 rsurface.modelsurfaces = model->data_surfaces;
6176 rsurface.vertex3f = rsurface.modelvertex3f;
6177 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6178 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6179 rsurface.svector3f = rsurface.modelsvector3f;
6180 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6181 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6182 rsurface.tvector3f = rsurface.modeltvector3f;
6183 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6184 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6185 rsurface.normal3f = rsurface.modelnormal3f;
6186 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6187 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6188 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6191 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)
6193 rsurface.entity = r_refdef.scene.worldentity;
6194 rsurface.skeleton = NULL;
6195 rsurface.ent_skinnum = 0;
6196 rsurface.ent_qwskin = -1;
6197 rsurface.ent_shadertime = shadertime;
6198 Vector4Set(rsurface.ent_color, r, g, b, a);
6199 rsurface.ent_flags = entflags;
6200 rsurface.modelnum_vertices = numvertices;
6201 rsurface.modelnum_triangles = numtriangles;
6202 if (rsurface.array_size < rsurface.modelnum_vertices)
6203 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6204 rsurface.matrix = *matrix;
6205 rsurface.inversematrix = *inversematrix;
6206 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6207 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6208 R_Mesh_Matrix(&rsurface.matrix);
6209 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6210 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6211 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6212 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6213 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6214 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6215 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6216 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6217 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6218 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6219 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6220 VectorSet(rsurface.glowmod, 1, 1, 1);
6221 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6222 rsurface.frameblend[0].lerp = 1;
6223 rsurface.ent_alttextures = false;
6224 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6225 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6228 rsurface.modelvertex3f = vertex3f;
6229 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6230 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6231 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6233 else if (wantnormals)
6235 rsurface.modelvertex3f = vertex3f;
6236 rsurface.modelsvector3f = NULL;
6237 rsurface.modeltvector3f = NULL;
6238 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6242 rsurface.modelvertex3f = vertex3f;
6243 rsurface.modelsvector3f = NULL;
6244 rsurface.modeltvector3f = NULL;
6245 rsurface.modelnormal3f = NULL;
6247 rsurface.modelvertex3f_bufferobject = 0;
6248 rsurface.modelvertex3f_bufferoffset = 0;
6249 rsurface.modelsvector3f_bufferobject = 0;
6250 rsurface.modelsvector3f_bufferoffset = 0;
6251 rsurface.modeltvector3f_bufferobject = 0;
6252 rsurface.modeltvector3f_bufferoffset = 0;
6253 rsurface.modelnormal3f_bufferobject = 0;
6254 rsurface.modelnormal3f_bufferoffset = 0;
6255 rsurface.generatedvertex = true;
6256 rsurface.modellightmapcolor4f = color4f;
6257 rsurface.modellightmapcolor4f_bufferobject = 0;
6258 rsurface.modellightmapcolor4f_bufferoffset = 0;
6259 rsurface.modeltexcoordtexture2f = texcoord2f;
6260 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6261 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6262 rsurface.modeltexcoordlightmap2f = NULL;
6263 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6264 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6265 rsurface.modelelement3i = element3i;
6266 rsurface.modelelement3s = element3s;
6267 rsurface.modelelement3i_bufferobject = 0;
6268 rsurface.modelelement3s_bufferobject = 0;
6269 rsurface.modellightmapoffsets = NULL;
6270 rsurface.modelsurfaces = NULL;
6271 rsurface.vertex3f = rsurface.modelvertex3f;
6272 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6273 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6274 rsurface.svector3f = rsurface.modelsvector3f;
6275 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6276 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6277 rsurface.tvector3f = rsurface.modeltvector3f;
6278 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6279 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6280 rsurface.normal3f = rsurface.modelnormal3f;
6281 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6282 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6283 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6285 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6287 if ((wantnormals || wanttangents) && !normal3f)
6288 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6289 if (wanttangents && !svector3f)
6290 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);
6294 float RSurf_FogPoint(const float *v)
6296 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6297 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6298 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6299 float FogHeightFade = r_refdef.fogheightfade;
6301 unsigned int fogmasktableindex;
6302 if (r_refdef.fogplaneviewabove)
6303 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6305 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6306 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6307 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6310 float RSurf_FogVertex(const float *v)
6312 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6313 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6314 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6315 float FogHeightFade = rsurface.fogheightfade;
6317 unsigned int fogmasktableindex;
6318 if (r_refdef.fogplaneviewabove)
6319 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6321 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6322 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6323 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6326 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6327 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6330 int texturesurfaceindex;
6335 const float *v1, *in_tc;
6337 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6339 q3shaderinfo_deform_t *deform;
6340 // 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
6341 if (rsurface.generatedvertex)
6343 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6344 generatenormals = true;
6345 for (i = 0;i < Q3MAXDEFORMS;i++)
6347 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6349 generatetangents = true;
6350 generatenormals = true;
6352 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6353 generatenormals = true;
6355 if (generatenormals && !rsurface.modelnormal3f)
6357 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6358 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6359 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6360 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6362 if (generatetangents && !rsurface.modelsvector3f)
6364 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6365 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6366 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6367 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6368 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6369 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6370 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);
6373 rsurface.vertex3f = rsurface.modelvertex3f;
6374 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6375 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6376 rsurface.svector3f = rsurface.modelsvector3f;
6377 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6378 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6379 rsurface.tvector3f = rsurface.modeltvector3f;
6380 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6381 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6382 rsurface.normal3f = rsurface.modelnormal3f;
6383 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6384 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6385 // if vertices are deformed (sprite flares and things in maps, possibly
6386 // water waves, bulges and other deformations), generate them into
6387 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6388 // (may be static model data or generated data for an animated model, or
6389 // the previous deform pass)
6390 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6392 switch (deform->deform)
6395 case Q3DEFORM_PROJECTIONSHADOW:
6396 case Q3DEFORM_TEXT0:
6397 case Q3DEFORM_TEXT1:
6398 case Q3DEFORM_TEXT2:
6399 case Q3DEFORM_TEXT3:
6400 case Q3DEFORM_TEXT4:
6401 case Q3DEFORM_TEXT5:
6402 case Q3DEFORM_TEXT6:
6403 case Q3DEFORM_TEXT7:
6406 case Q3DEFORM_AUTOSPRITE:
6407 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6408 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6409 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6410 VectorNormalize(newforward);
6411 VectorNormalize(newright);
6412 VectorNormalize(newup);
6413 // make deformed versions of only the model vertices used by the specified surfaces
6414 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6416 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6417 // a single autosprite surface can contain multiple sprites...
6418 for (j = 0;j < surface->num_vertices - 3;j += 4)
6420 VectorClear(center);
6421 for (i = 0;i < 4;i++)
6422 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6423 VectorScale(center, 0.25f, center);
6424 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6425 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6426 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6427 for (i = 0;i < 4;i++)
6429 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6430 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6433 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);
6434 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);
6436 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6437 rsurface.vertex3f_bufferobject = 0;
6438 rsurface.vertex3f_bufferoffset = 0;
6439 rsurface.svector3f = rsurface.array_deformedsvector3f;
6440 rsurface.svector3f_bufferobject = 0;
6441 rsurface.svector3f_bufferoffset = 0;
6442 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6443 rsurface.tvector3f_bufferobject = 0;
6444 rsurface.tvector3f_bufferoffset = 0;
6445 rsurface.normal3f = rsurface.array_deformednormal3f;
6446 rsurface.normal3f_bufferobject = 0;
6447 rsurface.normal3f_bufferoffset = 0;
6449 case Q3DEFORM_AUTOSPRITE2:
6450 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6451 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6452 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6453 VectorNormalize(newforward);
6454 VectorNormalize(newright);
6455 VectorNormalize(newup);
6456 // make deformed versions of only the model vertices used by the specified surfaces
6457 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6459 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6460 const float *v1, *v2;
6470 memset(shortest, 0, sizeof(shortest));
6471 // a single autosprite surface can contain multiple sprites...
6472 for (j = 0;j < surface->num_vertices - 3;j += 4)
6474 VectorClear(center);
6475 for (i = 0;i < 4;i++)
6476 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6477 VectorScale(center, 0.25f, center);
6478 // find the two shortest edges, then use them to define the
6479 // axis vectors for rotating around the central axis
6480 for (i = 0;i < 6;i++)
6482 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6483 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6485 Debug_PolygonBegin(NULL, 0);
6486 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6487 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);
6488 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6491 l = VectorDistance2(v1, v2);
6492 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6494 l += (1.0f / 1024.0f);
6495 if (shortest[0].length2 > l || i == 0)
6497 shortest[1] = shortest[0];
6498 shortest[0].length2 = l;
6499 shortest[0].v1 = v1;
6500 shortest[0].v2 = v2;
6502 else if (shortest[1].length2 > l || i == 1)
6504 shortest[1].length2 = l;
6505 shortest[1].v1 = v1;
6506 shortest[1].v2 = v2;
6509 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6510 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6512 Debug_PolygonBegin(NULL, 0);
6513 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6514 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);
6515 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6518 // this calculates the right vector from the shortest edge
6519 // and the up vector from the edge midpoints
6520 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6521 VectorNormalize(right);
6522 VectorSubtract(end, start, up);
6523 VectorNormalize(up);
6524 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6525 VectorSubtract(rsurface.localvieworigin, center, forward);
6526 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6527 VectorNegate(forward, forward);
6528 VectorReflect(forward, 0, up, forward);
6529 VectorNormalize(forward);
6530 CrossProduct(up, forward, newright);
6531 VectorNormalize(newright);
6533 Debug_PolygonBegin(NULL, 0);
6534 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);
6535 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6536 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6540 Debug_PolygonBegin(NULL, 0);
6541 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6542 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6543 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6546 // rotate the quad around the up axis vector, this is made
6547 // especially easy by the fact we know the quad is flat,
6548 // so we only have to subtract the center position and
6549 // measure distance along the right vector, and then
6550 // multiply that by the newright vector and add back the
6552 // we also need to subtract the old position to undo the
6553 // displacement from the center, which we do with a
6554 // DotProduct, the subtraction/addition of center is also
6555 // optimized into DotProducts here
6556 l = DotProduct(right, center);
6557 for (i = 0;i < 4;i++)
6559 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6560 f = DotProduct(right, v1) - l;
6561 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6564 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);
6565 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);
6567 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6568 rsurface.vertex3f_bufferobject = 0;
6569 rsurface.vertex3f_bufferoffset = 0;
6570 rsurface.svector3f = rsurface.array_deformedsvector3f;
6571 rsurface.svector3f_bufferobject = 0;
6572 rsurface.svector3f_bufferoffset = 0;
6573 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6574 rsurface.tvector3f_bufferobject = 0;
6575 rsurface.tvector3f_bufferoffset = 0;
6576 rsurface.normal3f = rsurface.array_deformednormal3f;
6577 rsurface.normal3f_bufferobject = 0;
6578 rsurface.normal3f_bufferoffset = 0;
6580 case Q3DEFORM_NORMAL:
6581 // deform the normals to make reflections wavey
6582 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6584 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6585 for (j = 0;j < surface->num_vertices;j++)
6588 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6589 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6590 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6591 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6592 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6593 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6594 VectorNormalize(normal);
6596 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);
6598 rsurface.svector3f = rsurface.array_deformedsvector3f;
6599 rsurface.svector3f_bufferobject = 0;
6600 rsurface.svector3f_bufferoffset = 0;
6601 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6602 rsurface.tvector3f_bufferobject = 0;
6603 rsurface.tvector3f_bufferoffset = 0;
6604 rsurface.normal3f = rsurface.array_deformednormal3f;
6605 rsurface.normal3f_bufferobject = 0;
6606 rsurface.normal3f_bufferoffset = 0;
6609 // deform vertex array to make wavey water and flags and such
6610 waveparms[0] = deform->waveparms[0];
6611 waveparms[1] = deform->waveparms[1];
6612 waveparms[2] = deform->waveparms[2];
6613 waveparms[3] = deform->waveparms[3];
6614 // this is how a divisor of vertex influence on deformation
6615 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6616 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6617 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6619 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6620 for (j = 0;j < surface->num_vertices;j++)
6622 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6623 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6624 // if the wavefunc depends on time, evaluate it per-vertex
6627 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6628 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6630 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6633 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6634 rsurface.vertex3f_bufferobject = 0;
6635 rsurface.vertex3f_bufferoffset = 0;
6637 case Q3DEFORM_BULGE:
6638 // deform vertex array to make the surface have moving bulges
6639 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6641 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6642 for (j = 0;j < surface->num_vertices;j++)
6644 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6645 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6648 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6649 rsurface.vertex3f_bufferobject = 0;
6650 rsurface.vertex3f_bufferoffset = 0;
6653 // deform vertex array
6654 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6655 VectorScale(deform->parms, scale, waveparms);
6656 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6658 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6659 for (j = 0;j < surface->num_vertices;j++)
6660 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6662 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6663 rsurface.vertex3f_bufferobject = 0;
6664 rsurface.vertex3f_bufferoffset = 0;
6668 // generate texcoords based on the chosen texcoord source
6669 switch(rsurface.texture->tcgen.tcgen)
6672 case Q3TCGEN_TEXTURE:
6673 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6674 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6675 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6677 case Q3TCGEN_LIGHTMAP:
6678 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6679 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6680 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6682 case Q3TCGEN_VECTOR:
6683 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6685 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6686 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)
6688 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6689 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6692 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6693 rsurface.texcoordtexture2f_bufferobject = 0;
6694 rsurface.texcoordtexture2f_bufferoffset = 0;
6696 case Q3TCGEN_ENVIRONMENT:
6697 // make environment reflections using a spheremap
6698 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6700 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6701 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6702 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6703 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6704 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6706 // identical to Q3A's method, but executed in worldspace so
6707 // carried models can be shiny too
6709 float viewer[3], d, reflected[3], worldreflected[3];
6711 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6712 // VectorNormalize(viewer);
6714 d = DotProduct(normal, viewer);
6716 reflected[0] = normal[0]*2*d - viewer[0];
6717 reflected[1] = normal[1]*2*d - viewer[1];
6718 reflected[2] = normal[2]*2*d - viewer[2];
6719 // note: this is proportinal to viewer, so we can normalize later
6721 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6722 VectorNormalize(worldreflected);
6724 // note: this sphere map only uses world x and z!
6725 // so positive and negative y will LOOK THE SAME.
6726 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6727 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6730 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6731 rsurface.texcoordtexture2f_bufferobject = 0;
6732 rsurface.texcoordtexture2f_bufferoffset = 0;
6735 // the only tcmod that needs software vertex processing is turbulent, so
6736 // check for it here and apply the changes if needed
6737 // and we only support that as the first one
6738 // (handling a mixture of turbulent and other tcmods would be problematic
6739 // without punting it entirely to a software path)
6740 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6742 amplitude = rsurface.texture->tcmods[0].parms[1];
6743 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6744 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6746 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6747 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)
6749 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6750 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6753 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6754 rsurface.texcoordtexture2f_bufferobject = 0;
6755 rsurface.texcoordtexture2f_bufferoffset = 0;
6757 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6758 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6759 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6760 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6763 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6766 const msurface_t *surface = texturesurfacelist[0];
6767 const msurface_t *surface2;
6772 // TODO: lock all array ranges before render, rather than on each surface
6773 if (texturenumsurfaces == 1)
6775 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6776 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);
6778 else if (r_batchmode.integer == 2)
6780 #define MAXBATCHTRIANGLES 4096
6781 int batchtriangles = 0;
6782 int batchelements[MAXBATCHTRIANGLES*3];
6783 for (i = 0;i < texturenumsurfaces;i = j)
6785 surface = texturesurfacelist[i];
6787 if (surface->num_triangles > MAXBATCHTRIANGLES)
6789 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);
6792 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6793 batchtriangles = surface->num_triangles;
6794 firstvertex = surface->num_firstvertex;
6795 endvertex = surface->num_firstvertex + surface->num_vertices;
6796 for (;j < texturenumsurfaces;j++)
6798 surface2 = texturesurfacelist[j];
6799 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6801 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6802 batchtriangles += surface2->num_triangles;
6803 firstvertex = min(firstvertex, surface2->num_firstvertex);
6804 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6806 surface2 = texturesurfacelist[j-1];
6807 numvertices = endvertex - firstvertex;
6808 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6811 else if (r_batchmode.integer == 1)
6813 for (i = 0;i < texturenumsurfaces;i = j)
6815 surface = texturesurfacelist[i];
6816 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6817 if (texturesurfacelist[j] != surface2)
6819 surface2 = texturesurfacelist[j-1];
6820 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6821 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6822 GL_LockArrays(surface->num_firstvertex, numvertices);
6823 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6828 for (i = 0;i < texturenumsurfaces;i++)
6830 surface = texturesurfacelist[i];
6831 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6832 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);
6837 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6839 int i, planeindex, vertexindex;
6843 r_waterstate_waterplane_t *p, *bestp;
6844 const msurface_t *surface;
6845 if (r_waterstate.renderingscene)
6847 for (i = 0;i < texturenumsurfaces;i++)
6849 surface = texturesurfacelist[i];
6850 if (lightmaptexunit >= 0)
6851 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6852 if (deluxemaptexunit >= 0)
6853 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6854 // pick the closest matching water plane
6857 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6860 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6862 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6863 d += fabs(PlaneDiff(vert, &p->plane));
6865 if (bestd > d || !bestp)
6873 if (refractiontexunit >= 0)
6874 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6875 if (reflectiontexunit >= 0)
6876 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6880 if (refractiontexunit >= 0)
6881 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6882 if (reflectiontexunit >= 0)
6883 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6885 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6886 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);
6890 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6894 const msurface_t *surface = texturesurfacelist[0];
6895 const msurface_t *surface2;
6900 // TODO: lock all array ranges before render, rather than on each surface
6901 if (texturenumsurfaces == 1)
6903 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6904 if (deluxemaptexunit >= 0)
6905 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
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);
6909 else if (r_batchmode.integer == 2)
6911 #define MAXBATCHTRIANGLES 4096
6912 int batchtriangles = 0;
6913 int batchelements[MAXBATCHTRIANGLES*3];
6914 for (i = 0;i < texturenumsurfaces;i = j)
6916 surface = texturesurfacelist[i];
6917 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6918 if (deluxemaptexunit >= 0)
6919 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6921 if (surface->num_triangles > MAXBATCHTRIANGLES)
6923 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);
6926 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6927 batchtriangles = surface->num_triangles;
6928 firstvertex = surface->num_firstvertex;
6929 endvertex = surface->num_firstvertex + surface->num_vertices;
6930 for (;j < texturenumsurfaces;j++)
6932 surface2 = texturesurfacelist[j];
6933 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6935 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6936 batchtriangles += surface2->num_triangles;
6937 firstvertex = min(firstvertex, surface2->num_firstvertex);
6938 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6940 surface2 = texturesurfacelist[j-1];
6941 numvertices = endvertex - firstvertex;
6942 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6945 else if (r_batchmode.integer == 1)
6948 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6949 for (i = 0;i < texturenumsurfaces;i = j)
6951 surface = texturesurfacelist[i];
6952 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6953 if (texturesurfacelist[j] != surface2)
6955 Con_Printf(" %i", j - i);
6958 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6960 for (i = 0;i < texturenumsurfaces;i = j)
6962 surface = texturesurfacelist[i];
6963 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6964 if (deluxemaptexunit >= 0)
6965 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6966 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6967 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6970 Con_Printf(" %i", j - i);
6972 surface2 = texturesurfacelist[j-1];
6973 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6974 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6975 GL_LockArrays(surface->num_firstvertex, numvertices);
6976 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6984 for (i = 0;i < texturenumsurfaces;i++)
6986 surface = texturesurfacelist[i];
6987 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6988 if (deluxemaptexunit >= 0)
6989 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6990 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6991 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);
6996 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6999 int texturesurfaceindex;
7000 if (r_showsurfaces.integer == 2)
7002 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7004 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7005 for (j = 0;j < surface->num_triangles;j++)
7007 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7008 GL_Color(f, f, f, 1);
7009 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7015 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7017 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7018 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7019 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);
7020 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7021 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);
7026 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7028 int texturesurfaceindex;
7032 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7034 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7035 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)
7043 rsurface.lightmapcolor4f = rsurface.array_color4f;
7044 rsurface.lightmapcolor4f_bufferobject = 0;
7045 rsurface.lightmapcolor4f_bufferoffset = 0;
7048 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7050 int texturesurfaceindex;
7056 if (rsurface.lightmapcolor4f)
7058 // generate color arrays for the surfaces in this list
7059 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7061 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7062 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)
7064 f = RSurf_FogVertex(v);
7074 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7076 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7077 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
7079 f = RSurf_FogVertex(v);
7087 rsurface.lightmapcolor4f = rsurface.array_color4f;
7088 rsurface.lightmapcolor4f_bufferobject = 0;
7089 rsurface.lightmapcolor4f_bufferoffset = 0;
7092 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7094 int texturesurfaceindex;
7100 if (!rsurface.lightmapcolor4f)
7102 // generate color arrays for the surfaces in this list
7103 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7105 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7106 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)
7108 f = RSurf_FogVertex(v);
7109 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7110 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7111 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7115 rsurface.lightmapcolor4f = rsurface.array_color4f;
7116 rsurface.lightmapcolor4f_bufferobject = 0;
7117 rsurface.lightmapcolor4f_bufferoffset = 0;
7120 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7122 int texturesurfaceindex;
7126 if (!rsurface.lightmapcolor4f)
7128 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7130 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7131 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)
7139 rsurface.lightmapcolor4f = rsurface.array_color4f;
7140 rsurface.lightmapcolor4f_bufferobject = 0;
7141 rsurface.lightmapcolor4f_bufferoffset = 0;
7144 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7146 int texturesurfaceindex;
7150 if (!rsurface.lightmapcolor4f)
7152 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7154 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7155 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)
7157 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7158 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7159 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7163 rsurface.lightmapcolor4f = rsurface.array_color4f;
7164 rsurface.lightmapcolor4f_bufferobject = 0;
7165 rsurface.lightmapcolor4f_bufferoffset = 0;
7168 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7171 rsurface.lightmapcolor4f = NULL;
7172 rsurface.lightmapcolor4f_bufferobject = 0;
7173 rsurface.lightmapcolor4f_bufferoffset = 0;
7174 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7175 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7176 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7177 GL_Color(r, g, b, a);
7178 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7181 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7183 // TODO: optimize applyfog && applycolor case
7184 // just apply fog if necessary, and tint the fog color array if necessary
7185 rsurface.lightmapcolor4f = NULL;
7186 rsurface.lightmapcolor4f_bufferobject = 0;
7187 rsurface.lightmapcolor4f_bufferoffset = 0;
7188 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7189 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7190 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7191 GL_Color(r, g, b, a);
7192 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7195 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7197 int texturesurfaceindex;
7201 if (texturesurfacelist[0]->lightmapinfo)
7203 // generate color arrays for the surfaces in this list
7204 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7206 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7207 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7209 if (surface->lightmapinfo->samples)
7211 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7212 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7213 VectorScale(lm, scale, c);
7214 if (surface->lightmapinfo->styles[1] != 255)
7216 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7218 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7219 VectorMA(c, scale, lm, c);
7220 if (surface->lightmapinfo->styles[2] != 255)
7223 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7224 VectorMA(c, scale, lm, c);
7225 if (surface->lightmapinfo->styles[3] != 255)
7228 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7229 VectorMA(c, scale, lm, c);
7239 rsurface.lightmapcolor4f = rsurface.array_color4f;
7240 rsurface.lightmapcolor4f_bufferobject = 0;
7241 rsurface.lightmapcolor4f_bufferoffset = 0;
7245 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7246 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7247 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7249 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7250 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7251 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7252 GL_Color(r, g, b, a);
7253 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7256 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7258 int texturesurfaceindex;
7265 vec3_t ambientcolor;
7266 vec3_t diffusecolor;
7270 VectorCopy(rsurface.modellight_lightdir, lightdir);
7271 f = 0.5f * r_refdef.lightmapintensity;
7272 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7273 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7274 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7275 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7276 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7277 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7279 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7281 // generate color arrays for the surfaces in this list
7282 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7284 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7285 int numverts = surface->num_vertices;
7286 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7287 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7288 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7289 // q3-style directional shading
7290 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7292 if ((f = DotProduct(n, lightdir)) > 0)
7293 VectorMA(ambientcolor, f, diffusecolor, c);
7295 VectorCopy(ambientcolor, c);
7303 rsurface.lightmapcolor4f = rsurface.array_color4f;
7304 rsurface.lightmapcolor4f_bufferobject = 0;
7305 rsurface.lightmapcolor4f_bufferoffset = 0;
7306 *applycolor = false;
7310 *r = ambientcolor[0];
7311 *g = ambientcolor[1];
7312 *b = ambientcolor[2];
7313 rsurface.lightmapcolor4f = NULL;
7314 rsurface.lightmapcolor4f_bufferobject = 0;
7315 rsurface.lightmapcolor4f_bufferoffset = 0;
7319 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7321 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7322 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7323 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7324 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7325 GL_Color(r, g, b, a);
7326 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7329 void RSurf_SetupDepthAndCulling(void)
7331 // submodels are biased to avoid z-fighting with world surfaces that they
7332 // may be exactly overlapping (avoids z-fighting artifacts on certain
7333 // doors and things in Quake maps)
7334 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7335 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7336 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7337 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7340 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7342 // transparent sky would be ridiculous
7343 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7345 R_SetupGenericShader(false);
7346 skyrenderlater = true;
7347 RSurf_SetupDepthAndCulling();
7349 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7350 // skymasking on them, and Quake3 never did sky masking (unlike
7351 // software Quake and software Quake2), so disable the sky masking
7352 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7353 // and skymasking also looks very bad when noclipping outside the
7354 // level, so don't use it then either.
7355 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7357 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7358 R_Mesh_ColorPointer(NULL, 0, 0);
7359 R_Mesh_ResetTextureState();
7360 if (skyrendermasked)
7362 R_SetupDepthOrShadowShader();
7363 // depth-only (masking)
7364 GL_ColorMask(0,0,0,0);
7365 // just to make sure that braindead drivers don't draw
7366 // anything despite that colormask...
7367 GL_BlendFunc(GL_ZERO, GL_ONE);
7371 R_SetupGenericShader(false);
7373 GL_BlendFunc(GL_ONE, GL_ZERO);
7375 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7376 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7377 if (skyrendermasked)
7378 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7380 R_Mesh_ResetTextureState();
7381 GL_Color(1, 1, 1, 1);
7384 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7386 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7389 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7390 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7391 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7392 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7393 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7394 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7395 if (rsurface.texture->backgroundcurrentskinframe)
7397 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7398 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7399 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7400 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7402 if(rsurface.texture->colormapping)
7404 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7405 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7407 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7408 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7409 R_Mesh_ColorPointer(NULL, 0, 0);
7411 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7413 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7415 // render background
7416 GL_BlendFunc(GL_ONE, GL_ZERO);
7418 GL_AlphaTest(false);
7420 GL_Color(1, 1, 1, 1);
7421 R_Mesh_ColorPointer(NULL, 0, 0);
7423 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7424 if (r_glsl_permutation)
7426 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7427 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7428 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7429 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7430 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7431 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7432 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);
7434 GL_LockArrays(0, 0);
7436 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7437 GL_DepthMask(false);
7438 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7439 R_Mesh_ColorPointer(NULL, 0, 0);
7441 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7442 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7443 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7446 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7447 if (!r_glsl_permutation)
7450 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7451 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7452 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7453 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7454 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7455 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7457 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7459 GL_BlendFunc(GL_ONE, GL_ZERO);
7461 GL_AlphaTest(false);
7465 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7466 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7467 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7470 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7472 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7473 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);
7475 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7479 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7480 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
7482 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7484 GL_LockArrays(0, 0);
7487 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7489 // OpenGL 1.3 path - anything not completely ancient
7490 int texturesurfaceindex;
7491 qboolean applycolor;
7495 const texturelayer_t *layer;
7496 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7498 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7501 int layertexrgbscale;
7502 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7504 if (layerindex == 0)
7508 GL_AlphaTest(false);
7509 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7512 GL_DepthMask(layer->depthmask && writedepth);
7513 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7514 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7516 layertexrgbscale = 4;
7517 VectorScale(layer->color, 0.25f, layercolor);
7519 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7521 layertexrgbscale = 2;
7522 VectorScale(layer->color, 0.5f, layercolor);
7526 layertexrgbscale = 1;
7527 VectorScale(layer->color, 1.0f, layercolor);
7529 layercolor[3] = layer->color[3];
7530 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7531 R_Mesh_ColorPointer(NULL, 0, 0);
7532 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7533 switch (layer->type)
7535 case TEXTURELAYERTYPE_LITTEXTURE:
7536 memset(&m, 0, sizeof(m));
7537 m.tex[0] = R_GetTexture(r_texture_white);
7538 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7539 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7540 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7541 m.tex[1] = R_GetTexture(layer->texture);
7542 m.texmatrix[1] = layer->texmatrix;
7543 m.texrgbscale[1] = layertexrgbscale;
7544 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7545 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7546 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7547 R_Mesh_TextureState(&m);
7548 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7549 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7550 else if (rsurface.uselightmaptexture)
7551 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7553 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7555 case TEXTURELAYERTYPE_TEXTURE:
7556 memset(&m, 0, sizeof(m));
7557 m.tex[0] = R_GetTexture(layer->texture);
7558 m.texmatrix[0] = layer->texmatrix;
7559 m.texrgbscale[0] = layertexrgbscale;
7560 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7561 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7562 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7563 R_Mesh_TextureState(&m);
7564 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7566 case TEXTURELAYERTYPE_FOG:
7567 memset(&m, 0, sizeof(m));
7568 m.texrgbscale[0] = layertexrgbscale;
7571 m.tex[0] = R_GetTexture(layer->texture);
7572 m.texmatrix[0] = layer->texmatrix;
7573 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7574 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7575 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7577 R_Mesh_TextureState(&m);
7578 // generate a color array for the fog pass
7579 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7580 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7586 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7587 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)
7589 f = 1 - RSurf_FogVertex(v);
7590 c[0] = layercolor[0];
7591 c[1] = layercolor[1];
7592 c[2] = layercolor[2];
7593 c[3] = f * layercolor[3];
7596 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7599 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7601 GL_LockArrays(0, 0);
7604 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7606 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7607 GL_AlphaTest(false);
7611 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7613 // OpenGL 1.1 - crusty old voodoo path
7614 int texturesurfaceindex;
7618 const texturelayer_t *layer;
7619 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7621 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7623 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7625 if (layerindex == 0)
7629 GL_AlphaTest(false);
7630 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7633 GL_DepthMask(layer->depthmask && writedepth);
7634 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7635 R_Mesh_ColorPointer(NULL, 0, 0);
7636 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7637 switch (layer->type)
7639 case TEXTURELAYERTYPE_LITTEXTURE:
7640 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7642 // two-pass lit texture with 2x rgbscale
7643 // first the lightmap pass
7644 memset(&m, 0, sizeof(m));
7645 m.tex[0] = R_GetTexture(r_texture_white);
7646 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7647 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7648 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7649 R_Mesh_TextureState(&m);
7650 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7651 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7652 else if (rsurface.uselightmaptexture)
7653 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7655 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7656 GL_LockArrays(0, 0);
7657 // then apply the texture to it
7658 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7659 memset(&m, 0, sizeof(m));
7660 m.tex[0] = R_GetTexture(layer->texture);
7661 m.texmatrix[0] = layer->texmatrix;
7662 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7663 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7664 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7665 R_Mesh_TextureState(&m);
7666 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);
7670 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7671 memset(&m, 0, sizeof(m));
7672 m.tex[0] = R_GetTexture(layer->texture);
7673 m.texmatrix[0] = layer->texmatrix;
7674 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7675 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7676 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7677 R_Mesh_TextureState(&m);
7678 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7679 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);
7681 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);
7684 case TEXTURELAYERTYPE_TEXTURE:
7685 // singletexture unlit texture with transparency support
7686 memset(&m, 0, sizeof(m));
7687 m.tex[0] = R_GetTexture(layer->texture);
7688 m.texmatrix[0] = layer->texmatrix;
7689 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7690 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7691 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7692 R_Mesh_TextureState(&m);
7693 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);
7695 case TEXTURELAYERTYPE_FOG:
7696 // singletexture fogging
7697 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7700 memset(&m, 0, sizeof(m));
7701 m.tex[0] = R_GetTexture(layer->texture);
7702 m.texmatrix[0] = layer->texmatrix;
7703 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7704 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7705 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7706 R_Mesh_TextureState(&m);
7709 R_Mesh_ResetTextureState();
7710 // generate a color array for the fog pass
7711 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7717 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7718 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)
7720 f = 1 - RSurf_FogVertex(v);
7721 c[0] = layer->color[0];
7722 c[1] = layer->color[1];
7723 c[2] = layer->color[2];
7724 c[3] = f * layer->color[3];
7727 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7730 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7732 GL_LockArrays(0, 0);
7735 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7737 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7738 GL_AlphaTest(false);
7742 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7746 GL_AlphaTest(false);
7747 R_Mesh_ColorPointer(NULL, 0, 0);
7748 R_Mesh_ResetTextureState();
7749 R_SetupGenericShader(false);
7751 if(rsurface.texture && rsurface.texture->currentskinframe)
7753 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7754 c[3] *= rsurface.texture->currentalpha;
7764 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7766 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7767 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7768 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7771 // brighten it up (as texture value 127 means "unlit")
7772 c[0] *= 2 * r_refdef.view.colorscale;
7773 c[1] *= 2 * r_refdef.view.colorscale;
7774 c[2] *= 2 * r_refdef.view.colorscale;
7776 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7777 c[3] *= r_wateralpha.value;
7779 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7781 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7782 GL_DepthMask(false);
7784 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7786 GL_BlendFunc(GL_ONE, GL_ONE);
7787 GL_DepthMask(false);
7789 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7791 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7792 GL_DepthMask(false);
7794 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7796 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7797 GL_DepthMask(false);
7801 GL_BlendFunc(GL_ONE, GL_ZERO);
7802 GL_DepthMask(writedepth);
7805 rsurface.lightmapcolor4f = NULL;
7807 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7809 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7811 rsurface.lightmapcolor4f = NULL;
7812 rsurface.lightmapcolor4f_bufferobject = 0;
7813 rsurface.lightmapcolor4f_bufferoffset = 0;
7815 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7817 qboolean applycolor = true;
7820 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7822 r_refdef.lightmapintensity = 1;
7823 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7824 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7828 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7830 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7831 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7832 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7835 if(!rsurface.lightmapcolor4f)
7836 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7838 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7839 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7840 if(r_refdef.fogenabled)
7841 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7843 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7844 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7847 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7850 RSurf_SetupDepthAndCulling();
7851 if (r_showsurfaces.integer == 3)
7852 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7853 else if (r_glsl.integer && gl_support_fragment_shader)
7854 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7855 else if (gl_combine.integer && r_textureunits.integer >= 2)
7856 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7858 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7862 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7865 RSurf_SetupDepthAndCulling();
7866 if (r_showsurfaces.integer == 3)
7867 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7868 else if (r_glsl.integer && gl_support_fragment_shader)
7869 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7870 else if (gl_combine.integer && r_textureunits.integer >= 2)
7871 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7873 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7877 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7880 int texturenumsurfaces, endsurface;
7882 const msurface_t *surface;
7883 const msurface_t *texturesurfacelist[1024];
7885 // if the model is static it doesn't matter what value we give for
7886 // wantnormals and wanttangents, so this logic uses only rules applicable
7887 // to a model, knowing that they are meaningless otherwise
7888 if (ent == r_refdef.scene.worldentity)
7889 RSurf_ActiveWorldEntity();
7890 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7891 RSurf_ActiveModelEntity(ent, false, false);
7893 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7895 for (i = 0;i < numsurfaces;i = j)
7898 surface = rsurface.modelsurfaces + surfacelist[i];
7899 texture = surface->texture;
7900 rsurface.texture = R_GetCurrentTexture(texture);
7901 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7902 // scan ahead until we find a different texture
7903 endsurface = min(i + 1024, numsurfaces);
7904 texturenumsurfaces = 0;
7905 texturesurfacelist[texturenumsurfaces++] = surface;
7906 for (;j < endsurface;j++)
7908 surface = rsurface.modelsurfaces + surfacelist[j];
7909 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7911 texturesurfacelist[texturenumsurfaces++] = surface;
7913 // render the range of surfaces
7914 if (ent == r_refdef.scene.worldentity)
7915 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7917 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7919 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7920 GL_AlphaTest(false);
7923 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7925 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7929 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7931 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7933 RSurf_SetupDepthAndCulling();
7934 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7935 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7937 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7939 RSurf_SetupDepthAndCulling();
7940 GL_AlphaTest(false);
7941 R_Mesh_ColorPointer(NULL, 0, 0);
7942 R_Mesh_ResetTextureState();
7943 R_SetupGenericShader(false);
7944 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7946 GL_BlendFunc(GL_ONE, GL_ZERO);
7947 GL_Color(0, 0, 0, 1);
7948 GL_DepthTest(writedepth);
7949 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7951 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7953 RSurf_SetupDepthAndCulling();
7954 GL_AlphaTest(false);
7955 R_Mesh_ColorPointer(NULL, 0, 0);
7956 R_Mesh_ResetTextureState();
7957 R_SetupGenericShader(false);
7958 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7960 GL_BlendFunc(GL_ONE, GL_ZERO);
7962 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7964 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7965 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7966 else if (!rsurface.texture->currentnumlayers)
7968 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7970 // transparent surfaces get pushed off into the transparent queue
7971 int surfacelistindex;
7972 const msurface_t *surface;
7973 vec3_t tempcenter, center;
7974 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7976 surface = texturesurfacelist[surfacelistindex];
7977 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7978 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7979 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7980 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7981 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7986 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7987 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7992 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7996 // break the surface list down into batches by texture and use of lightmapping
7997 for (i = 0;i < numsurfaces;i = j)
8000 // texture is the base texture pointer, rsurface.texture is the
8001 // current frame/skin the texture is directing us to use (for example
8002 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8003 // use skin 1 instead)
8004 texture = surfacelist[i]->texture;
8005 rsurface.texture = R_GetCurrentTexture(texture);
8006 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8007 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8009 // if this texture is not the kind we want, skip ahead to the next one
8010 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8014 // simply scan ahead until we find a different texture or lightmap state
8015 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8017 // render the range of surfaces
8018 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
8022 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
8027 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8029 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8031 RSurf_SetupDepthAndCulling();
8032 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8033 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8035 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8037 RSurf_SetupDepthAndCulling();
8038 GL_AlphaTest(false);
8039 R_Mesh_ColorPointer(NULL, 0, 0);
8040 R_Mesh_ResetTextureState();
8041 R_SetupGenericShader(false);
8042 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8044 GL_BlendFunc(GL_ONE, GL_ZERO);
8045 GL_Color(0, 0, 0, 1);
8046 GL_DepthTest(writedepth);
8047 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8049 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8051 RSurf_SetupDepthAndCulling();
8052 GL_AlphaTest(false);
8053 R_Mesh_ColorPointer(NULL, 0, 0);
8054 R_Mesh_ResetTextureState();
8055 R_SetupGenericShader(false);
8056 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8058 GL_BlendFunc(GL_ONE, GL_ZERO);
8060 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8062 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8063 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8064 else if (!rsurface.texture->currentnumlayers)
8066 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8068 // transparent surfaces get pushed off into the transparent queue
8069 int surfacelistindex;
8070 const msurface_t *surface;
8071 vec3_t tempcenter, center;
8072 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8074 surface = texturesurfacelist[surfacelistindex];
8075 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8076 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8077 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8078 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8079 if (queueentity->transparent_offset) // transparent offset
8081 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8082 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8083 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8085 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8090 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8091 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8096 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8100 // break the surface list down into batches by texture and use of lightmapping
8101 for (i = 0;i < numsurfaces;i = j)
8104 // texture is the base texture pointer, rsurface.texture is the
8105 // current frame/skin the texture is directing us to use (for example
8106 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8107 // use skin 1 instead)
8108 texture = surfacelist[i]->texture;
8109 rsurface.texture = R_GetCurrentTexture(texture);
8110 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8111 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8113 // if this texture is not the kind we want, skip ahead to the next one
8114 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8118 // simply scan ahead until we find a different texture or lightmap state
8119 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8121 // render the range of surfaces
8122 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8126 float locboxvertex3f[6*4*3] =
8128 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8129 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8130 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8131 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8132 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8133 1,0,0, 0,0,0, 0,1,0, 1,1,0
8136 unsigned short locboxelements[6*2*3] =
8146 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8149 cl_locnode_t *loc = (cl_locnode_t *)ent;
8151 float vertex3f[6*4*3];
8153 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8154 GL_DepthMask(false);
8155 GL_DepthRange(0, 1);
8156 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8158 GL_CullFace(GL_NONE);
8159 R_Mesh_Matrix(&identitymatrix);
8161 R_Mesh_VertexPointer(vertex3f, 0, 0);
8162 R_Mesh_ColorPointer(NULL, 0, 0);
8163 R_Mesh_ResetTextureState();
8164 R_SetupGenericShader(false);
8167 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8168 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8169 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8170 surfacelist[0] < 0 ? 0.5f : 0.125f);
8172 if (VectorCompare(loc->mins, loc->maxs))
8174 VectorSet(size, 2, 2, 2);
8175 VectorMA(loc->mins, -0.5f, size, mins);
8179 VectorCopy(loc->mins, mins);
8180 VectorSubtract(loc->maxs, loc->mins, size);
8183 for (i = 0;i < 6*4*3;)
8184 for (j = 0;j < 3;j++, i++)
8185 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8187 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8190 void R_DrawLocs(void)
8193 cl_locnode_t *loc, *nearestloc;
8195 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8196 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8198 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8199 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8203 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8205 if (decalsystem->decals)
8206 Mem_Free(decalsystem->decals);
8207 memset(decalsystem, 0, sizeof(*decalsystem));
8210 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, int decalsequence)
8217 // expand or initialize the system
8218 if (decalsystem->maxdecals <= decalsystem->numdecals)
8220 decalsystem_t old = *decalsystem;
8221 qboolean useshortelements;
8222 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8223 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8224 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)));
8225 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8226 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8227 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8228 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8229 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8230 if (decalsystem->numdecals)
8231 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8232 Mem_Free(old.decals);
8233 for (i = 0;i < decalsystem->maxdecals*3;i++)
8234 decalsystem->element3i[i] = i;
8235 if (useshortelements)
8236 for (i = 0;i < decalsystem->maxdecals*3;i++)
8237 decalsystem->element3s[i] = i;
8240 // grab a decal and search for another free slot for the next one
8241 maxdecals = decalsystem->maxdecals;
8242 decals = decalsystem->decals;
8243 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8244 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8246 decalsystem->freedecal = i;
8247 if (decalsystem->numdecals <= i)
8248 decalsystem->numdecals = i + 1;
8250 // initialize the decal
8252 decal->triangleindex = triangleindex;
8253 decal->surfaceindex = surfaceindex;
8254 decal->decalsequence = decalsequence;
8255 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8256 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8257 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8258 decal->color4ub[0][3] = 255;
8259 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8260 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8261 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8262 decal->color4ub[1][3] = 255;
8263 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8264 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8265 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8266 decal->color4ub[2][3] = 255;
8267 decal->vertex3f[0][0] = v0[0];
8268 decal->vertex3f[0][1] = v0[1];
8269 decal->vertex3f[0][2] = v0[2];
8270 decal->vertex3f[1][0] = v1[0];
8271 decal->vertex3f[1][1] = v1[1];
8272 decal->vertex3f[1][2] = v1[2];
8273 decal->vertex3f[2][0] = v2[0];
8274 decal->vertex3f[2][1] = v2[1];
8275 decal->vertex3f[2][2] = v2[2];
8276 decal->texcoord2f[0][0] = t0[0];
8277 decal->texcoord2f[0][1] = t0[1];
8278 decal->texcoord2f[1][0] = t1[0];
8279 decal->texcoord2f[1][1] = t1[1];
8280 decal->texcoord2f[2][0] = t2[0];
8281 decal->texcoord2f[2][1] = t2[1];
8284 extern cvar_t cl_decals_bias;
8285 extern cvar_t cl_decals_models;
8286 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8287 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
8289 matrix4x4_t projection;
8290 decalsystem_t *decalsystem;
8293 const float *vertex3f;
8294 const msurface_t *surface;
8295 const msurface_t *surfaces;
8296 const int *surfacelist;
8297 const texture_t *texture;
8301 int surfacelistindex;
8304 int decalsurfaceindex;
8309 float localorigin[3];
8310 float localnormal[3];
8321 float points[2][9][3];
8325 decalsystem = &ent->decalsystem;
8327 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8329 R_DecalSystem_Reset(&ent->decalsystem);
8333 if (!model->brush.data_nodes && !cl_decals_models.integer)
8335 if (decalsystem->model)
8336 R_DecalSystem_Reset(decalsystem);
8340 if (decalsystem->model != model)
8341 R_DecalSystem_Reset(decalsystem);
8342 decalsystem->model = model;
8344 RSurf_ActiveModelEntity(ent, false, false);
8346 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8347 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8348 VectorNormalize(localnormal);
8349 localsize = worldsize*rsurface.inversematrixscale;
8350 ilocalsize = 1.0f / localsize;
8351 localmins[0] = localorigin[0] - localsize;
8352 localmins[1] = localorigin[1] - localsize;
8353 localmins[2] = localorigin[2] - localsize;
8354 localmaxs[0] = localorigin[0] + localsize;
8355 localmaxs[1] = localorigin[1] + localsize;
8356 localmaxs[2] = localorigin[2] + localsize;
8358 //VectorCopy(localnormal, planes[4]);
8359 //VectorVectors(planes[4], planes[2], planes[0]);
8360 AnglesFromVectors(angles, localnormal, NULL, false);
8361 AngleVectors(angles, planes[0], planes[2], planes[4]);
8362 VectorNegate(planes[0], planes[1]);
8363 VectorNegate(planes[2], planes[3]);
8364 VectorNegate(planes[4], planes[5]);
8365 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8366 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8367 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8368 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8369 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8370 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8375 matrix4x4_t forwardprojection;
8376 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8377 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8382 float projectionvector[4][3];
8383 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8384 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8385 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8386 projectionvector[0][0] = planes[0][0] * ilocalsize;
8387 projectionvector[0][1] = planes[1][0] * ilocalsize;
8388 projectionvector[0][2] = planes[2][0] * ilocalsize;
8389 projectionvector[1][0] = planes[0][1] * ilocalsize;
8390 projectionvector[1][1] = planes[1][1] * ilocalsize;
8391 projectionvector[1][2] = planes[2][1] * ilocalsize;
8392 projectionvector[2][0] = planes[0][2] * ilocalsize;
8393 projectionvector[2][1] = planes[1][2] * ilocalsize;
8394 projectionvector[2][2] = planes[2][2] * ilocalsize;
8395 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8396 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8397 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8398 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8402 dynamic = model->surfmesh.isanimated;
8403 vertex3f = rsurface.modelvertex3f;
8404 numsurfacelist = model->nummodelsurfaces;
8405 surfacelist = model->sortedmodelsurfaces;
8406 surfaces = model->data_surfaces;
8407 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8409 surfaceindex = surfacelist[surfacelistindex];
8410 surface = surfaces + surfaceindex;
8411 // skip transparent surfaces
8412 texture = surface->texture;
8413 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8415 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8417 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8419 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8420 numvertices = surface->num_vertices;
8421 numtriangles = surface->num_triangles;
8422 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8424 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8426 index = 3*e[cornerindex];
8427 VectorCopy(vertex3f + index, v[cornerindex]);
8430 //TriangleNormal(v[0], v[1], v[2], normal);
8431 //if (DotProduct(normal, localnormal) < 0.0f)
8433 // clip by each of the box planes formed from the projection matrix
8434 // if anything survives, we emit the decal
8435 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]);
8438 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]);
8441 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]);
8444 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]);
8447 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]);
8450 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]);
8453 // some part of the triangle survived, so we have to accept it...
8456 // dynamic always uses the original triangle
8458 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8460 index = 3*e[cornerindex];
8461 VectorCopy(vertex3f + index, v[cornerindex]);
8464 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8466 // convert vertex positions to texcoords
8467 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8468 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8469 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8470 // calculate distance fade from the projection origin
8471 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8472 f = bound(0.0f, f, 1.0f);
8473 c[cornerindex][0] = r * f;
8474 c[cornerindex][1] = g * f;
8475 c[cornerindex][2] = b * f;
8476 c[cornerindex][3] = 1.0f;
8477 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8480 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex+surface->num_firsttriangle, surfaceindex, decalsequence);
8482 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8483 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
8488 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8489 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
8491 int renderentityindex;
8494 entity_render_t *ent;
8496 if (!cl_decals_newsystem.integer)
8499 worldmins[0] = worldorigin[0] - worldsize;
8500 worldmins[1] = worldorigin[1] - worldsize;
8501 worldmins[2] = worldorigin[2] - worldsize;
8502 worldmaxs[0] = worldorigin[0] + worldsize;
8503 worldmaxs[1] = worldorigin[1] + worldsize;
8504 worldmaxs[2] = worldorigin[2] + worldsize;
8506 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8508 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8510 ent = r_refdef.scene.entities[renderentityindex];
8511 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8514 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8518 typedef struct r_decalsystem_splatqueue_s
8527 r_decalsystem_splatqueue_t;
8529 int r_decalsystem_numqueued = 0;
8530 #define MAX_DECALSYSTEM_QUEUE 1024
8531 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8533 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)
8535 r_decalsystem_splatqueue_t *queue;
8537 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8540 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8541 VectorCopy(worldorigin, queue->worldorigin);
8542 VectorCopy(worldnormal, queue->worldnormal);
8543 Vector4Set(queue->color, r, g, b, a);
8544 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8545 queue->worldsize = worldsize;
8546 queue->decalsequence = cl.decalsequence++;
8549 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8552 r_decalsystem_splatqueue_t *queue;
8554 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8555 R_DecalSystem_ApplySplatEntities(queue->worldorigin, queue->worldnormal, queue->color[0], queue->color[1], queue->color[2], queue->color[3], queue->tcrange[0], queue->tcrange[1], queue->tcrange[2], queue->tcrange[3], queue->worldsize, queue->decalsequence);
8556 r_decalsystem_numqueued = 0;
8559 extern cvar_t cl_decals_max;
8560 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8563 decalsystem_t *decalsystem = &ent->decalsystem;
8570 if (!decalsystem->numdecals)
8573 if (r_showsurfaces.integer)
8576 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8578 R_DecalSystem_Reset(decalsystem);
8582 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
8583 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
8585 if (decalsystem->lastupdatetime)
8586 frametime = (cl.time - decalsystem->lastupdatetime);
8589 decalsystem->lastupdatetime = cl.time;
8590 decal = decalsystem->decals;
8591 numdecals = decalsystem->numdecals;
8593 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8595 if (decal->color4ub[0][3])
8597 decal->lived += frametime;
8598 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
8600 memset(decal, 0, sizeof(*decal));
8601 if (decalsystem->freedecal > i)
8602 decalsystem->freedecal = i;
8606 decal = decalsystem->decals;
8607 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
8610 // collapse the array by shuffling the tail decals into the gaps
8613 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
8614 decalsystem->freedecal++;
8615 if (decalsystem->freedecal == numdecals)
8617 decal[decalsystem->freedecal] = decal[--numdecals];
8620 decalsystem->numdecals = numdecals;
8624 // if there are no decals left, reset decalsystem
8625 R_DecalSystem_Reset(decalsystem);
8629 extern skinframe_t *decalskinframe;
8630 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8633 decalsystem_t *decalsystem = &ent->decalsystem;
8643 const unsigned char *surfacevisible = r_refdef.viewcache.world_surfacevisible;
8646 numdecals = decalsystem->numdecals;
8650 if (r_showsurfaces.integer)
8653 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8655 R_DecalSystem_Reset(decalsystem);
8659 // if the model is static it doesn't matter what value we give for
8660 // wantnormals and wanttangents, so this logic uses only rules applicable
8661 // to a model, knowing that they are meaningless otherwise
8662 if (ent == r_refdef.scene.worldentity)
8663 RSurf_ActiveWorldEntity();
8665 RSurf_ActiveModelEntity(ent, false, false);
8667 decalsystem->lastupdatetime = cl.time;
8668 decal = decalsystem->decals;
8670 fadedelay = cl_decals_time.value;
8671 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
8673 // update vertex positions for animated models
8674 v3f = decalsystem->vertex3f;
8675 c4f = decalsystem->color4f;
8676 t2f = decalsystem->texcoord2f;
8677 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8679 if (!decal->color4ub[0][3])
8682 if (decal->surfaceindex >= 0 && !surfacevisible[decal->surfaceindex])
8685 // update color values for fading decals
8686 if (decal->lived >= cl_decals_time.value)
8688 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
8689 alpha *= (1.0f/255.0f);
8692 alpha = 1.0f/255.0f;
8694 c4f[ 0] = decal->color4ub[0][0] * alpha;
8695 c4f[ 1] = decal->color4ub[0][1] * alpha;
8696 c4f[ 2] = decal->color4ub[0][2] * alpha;
8698 c4f[ 4] = decal->color4ub[1][0] * alpha;
8699 c4f[ 5] = decal->color4ub[1][1] * alpha;
8700 c4f[ 6] = decal->color4ub[1][2] * alpha;
8702 c4f[ 8] = decal->color4ub[2][0] * alpha;
8703 c4f[ 9] = decal->color4ub[2][1] * alpha;
8704 c4f[10] = decal->color4ub[2][2] * alpha;
8707 t2f[0] = decal->texcoord2f[0][0];
8708 t2f[1] = decal->texcoord2f[0][1];
8709 t2f[2] = decal->texcoord2f[1][0];
8710 t2f[3] = decal->texcoord2f[1][1];
8711 t2f[4] = decal->texcoord2f[2][0];
8712 t2f[5] = decal->texcoord2f[2][1];
8714 // update vertex positions for animated models
8715 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8717 e = rsurface.modelelement3i + 3*decal->triangleindex;
8718 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8719 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8720 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8724 VectorCopy(decal->vertex3f[0], v3f);
8725 VectorCopy(decal->vertex3f[1], v3f + 3);
8726 VectorCopy(decal->vertex3f[2], v3f + 6);
8737 r_refdef.stats.drawndecals += numtris;
8738 // now render the decals all at once
8739 // (this assumes they all use one particle font texture!)
8740 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
8741 R_Mesh_ResetTextureState();
8742 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8743 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8744 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8745 R_SetupGenericShader(true);
8746 GL_DepthMask(false);
8747 GL_DepthRange(0, 1);
8748 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
8750 GL_CullFace(GL_NONE);
8751 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8752 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8753 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8754 GL_LockArrays(0, numtris * 3);
8755 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
8756 GL_LockArrays(0, 0);
8760 static void R_DrawModelDecals(void)
8764 // fade faster when there are too many decals
8765 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
8766 for (i = 0;i < r_refdef.scene.numentities;i++)
8767 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
8769 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
8770 for (i = 0;i < r_refdef.scene.numentities;i++)
8771 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
8772 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
8774 R_DecalSystem_ApplySplatEntitiesQueue();
8776 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
8777 for (i = 0;i < r_refdef.scene.numentities;i++)
8778 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
8780 r_refdef.stats.totaldecals += numdecals;
8782 if (r_showsurfaces.integer)
8785 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
8787 if (!r_drawentities.integer)
8790 for (i = 0;i < r_refdef.scene.numentities;i++)
8792 if (!r_refdef.viewcache.entityvisible[i])
8794 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
8795 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
8799 void R_DrawDebugModel(void)
8801 entity_render_t *ent = rsurface.entity;
8802 int i, j, k, l, flagsmask;
8803 const int *elements;
8805 const msurface_t *surface;
8806 dp_model_t *model = ent->model;
8809 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8811 R_Mesh_ColorPointer(NULL, 0, 0);
8812 R_Mesh_ResetTextureState();
8813 R_SetupGenericShader(false);
8814 GL_DepthRange(0, 1);
8815 GL_DepthTest(!r_showdisabledepthtest.integer);
8816 GL_DepthMask(false);
8817 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8819 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8821 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8822 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8824 if (brush->colbrushf && brush->colbrushf->numtriangles)
8826 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8827 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);
8828 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8831 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8833 if (surface->num_collisiontriangles)
8835 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8836 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);
8837 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8842 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8844 if (r_showtris.integer || r_shownormals.integer)
8846 if (r_showdisabledepthtest.integer)
8848 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8849 GL_DepthMask(false);
8853 GL_BlendFunc(GL_ONE, GL_ZERO);
8856 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8858 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8860 rsurface.texture = R_GetCurrentTexture(surface->texture);
8861 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8863 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8864 if (r_showtris.value > 0)
8866 if (!rsurface.texture->currentlayers->depthmask)
8867 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8868 else if (ent == r_refdef.scene.worldentity)
8869 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8871 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8872 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8873 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8874 R_Mesh_ColorPointer(NULL, 0, 0);
8875 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8876 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8877 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8878 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);
8879 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8882 if (r_shownormals.value < 0)
8885 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8887 VectorCopy(rsurface.vertex3f + l * 3, v);
8888 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8889 qglVertex3f(v[0], v[1], v[2]);
8890 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8891 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8892 qglVertex3f(v[0], v[1], v[2]);
8897 if (r_shownormals.value > 0)
8900 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8902 VectorCopy(rsurface.vertex3f + l * 3, v);
8903 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8904 qglVertex3f(v[0], v[1], v[2]);
8905 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8906 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8907 qglVertex3f(v[0], v[1], v[2]);
8912 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8914 VectorCopy(rsurface.vertex3f + l * 3, v);
8915 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8916 qglVertex3f(v[0], v[1], v[2]);
8917 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8918 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8919 qglVertex3f(v[0], v[1], v[2]);
8924 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8926 VectorCopy(rsurface.vertex3f + l * 3, v);
8927 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8928 qglVertex3f(v[0], v[1], v[2]);
8929 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8930 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8931 qglVertex3f(v[0], v[1], v[2]);
8938 rsurface.texture = NULL;
8942 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8943 int r_maxsurfacelist = 0;
8944 const msurface_t **r_surfacelist = NULL;
8945 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8947 int i, j, endj, f, flagsmask;
8949 dp_model_t *model = r_refdef.scene.worldmodel;
8950 msurface_t *surfaces;
8951 unsigned char *update;
8952 int numsurfacelist = 0;
8956 if (r_maxsurfacelist < model->num_surfaces)
8958 r_maxsurfacelist = model->num_surfaces;
8960 Mem_Free((msurface_t**)r_surfacelist);
8961 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8964 RSurf_ActiveWorldEntity();
8966 surfaces = model->data_surfaces;
8967 update = model->brushq1.lightmapupdateflags;
8969 // update light styles on this submodel
8970 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8972 model_brush_lightstyleinfo_t *style;
8973 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8975 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8977 int *list = style->surfacelist;
8978 style->value = r_refdef.scene.lightstylevalue[style->style];
8979 for (j = 0;j < style->numsurfaces;j++)
8980 update[list[j]] = true;
8985 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8990 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8996 rsurface.uselightmaptexture = false;
8997 rsurface.texture = NULL;
8998 rsurface.rtlight = NULL;
9000 // add visible surfaces to draw list
9001 for (i = 0;i < model->nummodelsurfaces;i++)
9003 j = model->sortedmodelsurfaces[i];
9004 if (r_refdef.viewcache.world_surfacevisible[j])
9005 r_surfacelist[numsurfacelist++] = surfaces + j;
9007 // update lightmaps if needed
9009 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9010 if (r_refdef.viewcache.world_surfacevisible[j])
9012 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9013 // don't do anything if there were no surfaces
9014 if (!numsurfacelist)
9016 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9019 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
9020 GL_AlphaTest(false);
9022 // add to stats if desired
9023 if (r_speeds.integer && !skysurfaces && !depthonly)
9025 r_refdef.stats.world_surfaces += numsurfacelist;
9026 for (j = 0;j < numsurfacelist;j++)
9027 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9030 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9033 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
9035 int i, j, endj, f, flagsmask;
9037 dp_model_t *model = ent->model;
9038 msurface_t *surfaces;
9039 unsigned char *update;
9040 int numsurfacelist = 0;
9044 if (r_maxsurfacelist < model->num_surfaces)
9046 r_maxsurfacelist = model->num_surfaces;
9048 Mem_Free((msurface_t **)r_surfacelist);
9049 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9052 // if the model is static it doesn't matter what value we give for
9053 // wantnormals and wanttangents, so this logic uses only rules applicable
9054 // to a model, knowing that they are meaningless otherwise
9055 if (ent == r_refdef.scene.worldentity)
9056 RSurf_ActiveWorldEntity();
9057 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9058 RSurf_ActiveModelEntity(ent, false, false);
9060 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
9062 surfaces = model->data_surfaces;
9063 update = model->brushq1.lightmapupdateflags;
9065 // update light styles
9066 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9068 model_brush_lightstyleinfo_t *style;
9069 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9071 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9073 int *list = style->surfacelist;
9074 style->value = r_refdef.scene.lightstylevalue[style->style];
9075 for (j = 0;j < style->numsurfaces;j++)
9076 update[list[j]] = true;
9081 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9086 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9092 rsurface.uselightmaptexture = false;
9093 rsurface.texture = NULL;
9094 rsurface.rtlight = NULL;
9096 // add visible surfaces to draw list
9097 for (i = 0;i < model->nummodelsurfaces;i++)
9098 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9099 // don't do anything if there were no surfaces
9100 if (!numsurfacelist)
9102 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9105 // update lightmaps if needed
9107 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9109 R_BuildLightMap(ent, surfaces + j);
9110 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
9111 GL_AlphaTest(false);
9113 // add to stats if desired
9114 if (r_speeds.integer && !skysurfaces && !depthonly)
9116 r_refdef.stats.entities_surfaces += numsurfacelist;
9117 for (j = 0;j < numsurfacelist;j++)
9118 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9121 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9124 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
9126 static texture_t texture;
9127 static msurface_t surface;
9128 const msurface_t *surfacelist = &surface;
9130 // fake enough texture and surface state to render this geometry
9132 texture.update_lastrenderframe = -1; // regenerate this texture
9133 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9134 texture.currentskinframe = skinframe;
9135 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9136 texture.specularscalemod = 1;
9137 texture.specularpowermod = 1;
9139 surface.texture = &texture;
9140 surface.num_triangles = numtriangles;
9141 surface.num_firsttriangle = firsttriangle;
9142 surface.num_vertices = numvertices;
9143 surface.num_firstvertex = firstvertex;
9146 rsurface.texture = R_GetCurrentTexture(surface.texture);
9147 rsurface.uselightmaptexture = false;
9148 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);