2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
33 qboolean r_loadnormalmap;
42 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
43 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
44 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
45 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
46 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
47 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
48 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
49 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
51 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
52 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
53 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
54 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
55 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
57 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
59 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
60 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
61 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
62 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
63 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
64 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
65 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
66 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
67 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
68 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
69 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
71 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
72 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
73 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
74 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
75 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
76 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
77 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
78 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
79 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
80 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
81 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
82 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
83 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
84 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
85 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
86 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
87 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
88 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
89 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
90 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
91 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
92 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
93 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
94 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
95 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
96 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
97 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
99 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
102 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
103 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
104 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
105 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
106 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
107 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
108 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
110 cvar_t r_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)"};
111 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
112 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
113 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
114 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
115 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)"};
116 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)"};
117 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)"};
118 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)"};
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_PRECACHE | 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("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2027 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2028 qglUseProgramObjectARB(0);CHECKGLERROR
2029 return; // no bit left to clear, entire mode is broken
2034 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2038 void R_SetupGenericShader(qboolean usetexture)
2040 if (vid.support.arb_fragment_shader)
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 (vid.support.arb_fragment_shader)
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)
2065 R_Mesh_TexCombine(1, GL_DECAL, GL_DECAL, 1, 1);
2068 void R_SetupDepthOrShadowShader(void)
2070 if (vid.support.arb_fragment_shader)
2073 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2074 else if (r_glsl_permutation)
2076 r_glsl_permutation = NULL;
2077 qglUseProgramObjectARB(0);CHECKGLERROR
2082 void R_SetupShowDepthShader(void)
2084 if (vid.support.arb_fragment_shader)
2087 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2088 else if (r_glsl_permutation)
2090 r_glsl_permutation = NULL;
2091 qglUseProgramObjectARB(0);CHECKGLERROR
2096 extern rtexture_t *r_shadow_attenuationgradienttexture;
2097 extern rtexture_t *r_shadow_attenuation2dtexture;
2098 extern rtexture_t *r_shadow_attenuation3dtexture;
2099 extern qboolean r_shadow_usingshadowmaprect;
2100 extern qboolean r_shadow_usingshadowmapcube;
2101 extern qboolean r_shadow_usingshadowmap2d;
2102 extern float r_shadow_shadowmap_texturescale[2];
2103 extern float r_shadow_shadowmap_parameters[4];
2104 extern qboolean r_shadow_shadowmapvsdct;
2105 extern qboolean r_shadow_shadowmapsampler;
2106 extern int r_shadow_shadowmappcf;
2107 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2109 // select a permutation of the lighting shader appropriate to this
2110 // combination of texture, entity, light source, and fogging, only use the
2111 // minimum features necessary to avoid wasting rendering time in the
2112 // fragment shader on features that are not being used
2113 unsigned int permutation = 0;
2114 unsigned int mode = 0;
2115 // TODO: implement geometry-shader based shadow volumes someday
2116 if (r_glsl_offsetmapping.integer)
2118 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2119 if (r_glsl_offsetmapping_reliefmapping.integer)
2120 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2122 if (rsurfacepass == RSURFPASS_BACKGROUND)
2124 // distorted background
2125 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2126 mode = SHADERMODE_WATER;
2128 mode = SHADERMODE_REFRACTION;
2130 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2133 mode = SHADERMODE_LIGHTSOURCE;
2134 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2135 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2136 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2137 permutation |= SHADERPERMUTATION_CUBEFILTER;
2138 if (diffusescale > 0)
2139 permutation |= SHADERPERMUTATION_DIFFUSE;
2140 if (specularscale > 0)
2141 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2142 if (r_refdef.fogenabled)
2143 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2144 if (rsurface.texture->colormapping)
2145 permutation |= SHADERPERMUTATION_COLORMAPPING;
2146 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2148 if (r_shadow_usingshadowmaprect)
2149 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2150 if (r_shadow_usingshadowmap2d)
2151 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2152 if (r_shadow_usingshadowmapcube)
2153 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2154 else if(r_shadow_shadowmapvsdct)
2155 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2157 if (r_shadow_shadowmapsampler)
2158 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2159 if (r_shadow_shadowmappcf > 1)
2160 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2161 else if (r_shadow_shadowmappcf)
2162 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2165 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2167 // unshaded geometry (fullbright or ambient model lighting)
2168 mode = SHADERMODE_FLATCOLOR;
2169 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2171 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2172 permutation |= SHADERPERMUTATION_GLOW;
2173 if (r_refdef.fogenabled)
2174 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2175 if (rsurface.texture->colormapping)
2176 permutation |= SHADERPERMUTATION_COLORMAPPING;
2177 if (r_glsl_offsetmapping.integer)
2179 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2180 if (r_glsl_offsetmapping_reliefmapping.integer)
2181 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2183 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2184 permutation |= SHADERPERMUTATION_REFLECTION;
2186 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2188 // directional model lighting
2189 mode = SHADERMODE_LIGHTDIRECTION;
2190 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2191 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2192 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2193 permutation |= SHADERPERMUTATION_GLOW;
2194 permutation |= SHADERPERMUTATION_DIFFUSE;
2195 if (specularscale > 0)
2196 permutation |= SHADERPERMUTATION_SPECULAR;
2197 if (r_refdef.fogenabled)
2198 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2199 if (rsurface.texture->colormapping)
2200 permutation |= SHADERPERMUTATION_COLORMAPPING;
2201 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2202 permutation |= SHADERPERMUTATION_REFLECTION;
2204 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2206 // ambient model lighting
2207 mode = SHADERMODE_LIGHTDIRECTION;
2208 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2209 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2210 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2211 permutation |= SHADERPERMUTATION_GLOW;
2212 if (r_refdef.fogenabled)
2213 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2214 if (rsurface.texture->colormapping)
2215 permutation |= SHADERPERMUTATION_COLORMAPPING;
2216 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2217 permutation |= SHADERPERMUTATION_REFLECTION;
2222 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2224 // deluxemapping (light direction texture)
2225 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2226 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2228 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2229 permutation |= SHADERPERMUTATION_DIFFUSE;
2230 if (specularscale > 0)
2231 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2233 else if (r_glsl_deluxemapping.integer >= 2)
2235 // fake deluxemapping (uniform light direction in tangentspace)
2236 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2237 permutation |= SHADERPERMUTATION_DIFFUSE;
2238 if (specularscale > 0)
2239 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2241 else if (rsurface.uselightmaptexture)
2243 // ordinary lightmapping (q1bsp, q3bsp)
2244 mode = SHADERMODE_LIGHTMAP;
2248 // ordinary vertex coloring (q3bsp)
2249 mode = SHADERMODE_VERTEXCOLOR;
2251 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2252 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2253 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2254 permutation |= SHADERPERMUTATION_GLOW;
2255 if (r_refdef.fogenabled)
2256 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2257 if (rsurface.texture->colormapping)
2258 permutation |= SHADERPERMUTATION_COLORMAPPING;
2259 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2260 permutation |= SHADERPERMUTATION_REFLECTION;
2262 if(permutation & SHADERPERMUTATION_SPECULAR)
2263 if(r_shadow_glossexact.integer)
2264 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2265 R_SetupShader_SetPermutation(mode, permutation);
2266 if (mode == SHADERMODE_LIGHTSOURCE)
2268 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2269 if (permutation & SHADERPERMUTATION_DIFFUSE)
2271 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2272 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2273 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2274 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2278 // ambient only is simpler
2279 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]);
2280 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2281 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2282 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2284 // additive passes are only darkened by fog, not tinted
2285 if (r_glsl_permutation->loc_FogColor >= 0)
2286 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2287 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]);
2288 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]);
2292 if (mode == SHADERMODE_LIGHTDIRECTION)
2294 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);
2295 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);
2296 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);
2297 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]);
2301 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2302 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2303 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2305 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]);
2306 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);
2307 // additive passes are only darkened by fog, not tinted
2308 if (r_glsl_permutation->loc_FogColor >= 0)
2310 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2311 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2313 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2315 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);
2316 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]);
2317 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]);
2318 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2319 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2320 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2321 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2323 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2324 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2325 if (r_glsl_permutation->loc_Color_Pants >= 0)
2327 if (rsurface.texture->currentskinframe->pants)
2328 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2330 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2332 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2334 if (rsurface.texture->currentskinframe->shirt)
2335 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2337 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2339 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]);
2340 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2341 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2342 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2343 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2345 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2349 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2351 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2355 #define SKINFRAME_HASH 1024
2359 int loadsequence; // incremented each level change
2360 memexpandablearray_t array;
2361 skinframe_t *hash[SKINFRAME_HASH];
2364 r_skinframe_t r_skinframe;
2366 void R_SkinFrame_PrepareForPurge(void)
2368 r_skinframe.loadsequence++;
2369 // wrap it without hitting zero
2370 if (r_skinframe.loadsequence >= 200)
2371 r_skinframe.loadsequence = 1;
2374 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2378 // mark the skinframe as used for the purging code
2379 skinframe->loadsequence = r_skinframe.loadsequence;
2382 void R_SkinFrame_Purge(void)
2386 for (i = 0;i < SKINFRAME_HASH;i++)
2388 for (s = r_skinframe.hash[i];s;s = s->next)
2390 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2392 if (s->merged == s->base)
2394 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2395 R_PurgeTexture(s->stain );s->stain = NULL;
2396 R_PurgeTexture(s->merged);s->merged = NULL;
2397 R_PurgeTexture(s->base );s->base = NULL;
2398 R_PurgeTexture(s->pants );s->pants = NULL;
2399 R_PurgeTexture(s->shirt );s->shirt = NULL;
2400 R_PurgeTexture(s->nmap );s->nmap = NULL;
2401 R_PurgeTexture(s->gloss );s->gloss = NULL;
2402 R_PurgeTexture(s->glow );s->glow = NULL;
2403 R_PurgeTexture(s->fog );s->fog = NULL;
2404 s->loadsequence = 0;
2410 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2412 char basename[MAX_QPATH];
2414 Image_StripImageExtension(name, basename, sizeof(basename));
2416 if( last == NULL ) {
2418 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2419 item = r_skinframe.hash[hashindex];
2424 // linearly search through the hash bucket
2425 for( ; item ; item = item->next ) {
2426 if( !strcmp( item->basename, basename ) ) {
2433 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2437 char basename[MAX_QPATH];
2439 Image_StripImageExtension(name, basename, sizeof(basename));
2441 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2442 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2443 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2447 rtexture_t *dyntexture;
2448 // check whether its a dynamic texture
2449 dyntexture = CL_GetDynTexture( basename );
2450 if (!add && !dyntexture)
2452 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2453 memset(item, 0, sizeof(*item));
2454 strlcpy(item->basename, basename, sizeof(item->basename));
2455 item->base = dyntexture; // either NULL or dyntexture handle
2456 item->textureflags = textureflags;
2457 item->comparewidth = comparewidth;
2458 item->compareheight = compareheight;
2459 item->comparecrc = comparecrc;
2460 item->next = r_skinframe.hash[hashindex];
2461 r_skinframe.hash[hashindex] = item;
2463 else if( item->base == NULL )
2465 rtexture_t *dyntexture;
2466 // check whether its a dynamic texture
2467 // 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]
2468 dyntexture = CL_GetDynTexture( basename );
2469 item->base = dyntexture; // either NULL or dyntexture handle
2472 R_SkinFrame_MarkUsed(item);
2476 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2478 unsigned long long avgcolor[5], wsum; \
2486 for(pix = 0; pix < cnt; ++pix) \
2489 for(comp = 0; comp < 3; ++comp) \
2491 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2494 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2496 for(comp = 0; comp < 3; ++comp) \
2497 avgcolor[comp] += getpixel * w; \
2500 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2501 avgcolor[4] += getpixel; \
2503 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2505 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2506 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2507 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2508 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2511 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2514 unsigned char *pixels;
2515 unsigned char *bumppixels;
2516 unsigned char *basepixels = NULL;
2517 int basepixels_width;
2518 int basepixels_height;
2519 skinframe_t *skinframe;
2521 if (cls.state == ca_dedicated)
2524 // return an existing skinframe if already loaded
2525 // if loading of the first image fails, don't make a new skinframe as it
2526 // would cause all future lookups of this to be missing
2527 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2528 if (skinframe && skinframe->base)
2531 basepixels = loadimagepixelsbgra(name, complain, true);
2532 if (basepixels == NULL)
2535 if (developer_loading.integer)
2536 Con_Printf("loading skin \"%s\"\n", name);
2538 // we've got some pixels to store, so really allocate this new texture now
2540 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2541 skinframe->stain = NULL;
2542 skinframe->merged = NULL;
2543 skinframe->base = r_texture_notexture;
2544 skinframe->pants = NULL;
2545 skinframe->shirt = NULL;
2546 skinframe->nmap = r_texture_blanknormalmap;
2547 skinframe->gloss = NULL;
2548 skinframe->glow = NULL;
2549 skinframe->fog = NULL;
2550 skinframe->hasalpha = false;
2552 basepixels_width = image_width;
2553 basepixels_height = image_height;
2554 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);
2556 if (textureflags & TEXF_ALPHA)
2558 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2560 if (basepixels[j] < 255)
2562 skinframe->hasalpha = true;
2566 if (r_loadfog && skinframe->hasalpha)
2568 // has transparent pixels
2569 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2570 for (j = 0;j < image_width * image_height * 4;j += 4)
2575 pixels[j+3] = basepixels[j+3];
2577 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);
2582 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2583 //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]);
2585 // _norm is the name used by tenebrae and has been adopted as standard
2586 if (r_loadnormalmap)
2588 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2590 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);
2594 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2596 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2597 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2598 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);
2600 Mem_Free(bumppixels);
2602 else if (r_shadow_bumpscale_basetexture.value > 0)
2604 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2605 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2606 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);
2610 // _luma is supported for tenebrae compatibility
2611 // (I think it's a very stupid name, but oh well)
2612 // _glow is the preferred name
2613 if ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2614 if (r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false))) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2615 if ((pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false))) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2616 if ((pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false))) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2619 Mem_Free(basepixels);
2624 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2625 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2628 unsigned char *temp1, *temp2;
2629 skinframe_t *skinframe;
2631 if (cls.state == ca_dedicated)
2634 // if already loaded just return it, otherwise make a new skinframe
2635 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2636 if (skinframe && skinframe->base)
2639 skinframe->stain = NULL;
2640 skinframe->merged = NULL;
2641 skinframe->base = r_texture_notexture;
2642 skinframe->pants = NULL;
2643 skinframe->shirt = NULL;
2644 skinframe->nmap = r_texture_blanknormalmap;
2645 skinframe->gloss = NULL;
2646 skinframe->glow = NULL;
2647 skinframe->fog = NULL;
2648 skinframe->hasalpha = false;
2650 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2654 if (developer_loading.integer)
2655 Con_Printf("loading 32bit skin \"%s\"\n", name);
2657 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2659 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2660 temp2 = temp1 + width * height * 4;
2661 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2662 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2665 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2666 if (textureflags & TEXF_ALPHA)
2668 for (i = 3;i < width * height * 4;i += 4)
2670 if (skindata[i] < 255)
2672 skinframe->hasalpha = true;
2676 if (r_loadfog && skinframe->hasalpha)
2678 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2679 memcpy(fogpixels, skindata, width * height * 4);
2680 for (i = 0;i < width * height * 4;i += 4)
2681 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2682 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2683 Mem_Free(fogpixels);
2687 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2688 //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]);
2693 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2697 skinframe_t *skinframe;
2699 if (cls.state == ca_dedicated)
2702 // if already loaded just return it, otherwise make a new skinframe
2703 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2704 if (skinframe && skinframe->base)
2707 skinframe->stain = NULL;
2708 skinframe->merged = NULL;
2709 skinframe->base = r_texture_notexture;
2710 skinframe->pants = NULL;
2711 skinframe->shirt = NULL;
2712 skinframe->nmap = r_texture_blanknormalmap;
2713 skinframe->gloss = NULL;
2714 skinframe->glow = NULL;
2715 skinframe->fog = NULL;
2716 skinframe->hasalpha = false;
2718 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2722 if (developer_loading.integer)
2723 Con_Printf("loading quake skin \"%s\"\n", name);
2725 // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
2726 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
2727 memcpy(skinframe->qpixels, skindata, width*height);
2728 skinframe->qwidth = width;
2729 skinframe->qheight = height;
2732 for (i = 0;i < width * height;i++)
2733 featuresmask |= palette_featureflags[skindata[i]];
2735 skinframe->hasalpha = false;
2736 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2737 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2738 skinframe->qgeneratemerged = true;
2739 skinframe->qgeneratebase = skinframe->qhascolormapping;
2740 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2742 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2743 //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]);
2748 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2752 unsigned char *skindata;
2754 if (!skinframe->qpixels)
2757 if (!skinframe->qhascolormapping)
2758 colormapped = false;
2762 if (!skinframe->qgeneratebase)
2767 if (!skinframe->qgeneratemerged)
2771 width = skinframe->qwidth;
2772 height = skinframe->qheight;
2773 skindata = skinframe->qpixels;
2775 if (skinframe->qgeneratenmap)
2777 unsigned char *temp1, *temp2;
2778 skinframe->qgeneratenmap = false;
2779 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2780 temp2 = temp1 + width * height * 4;
2781 // use either a custom palette or the quake palette
2782 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2783 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2784 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2788 if (skinframe->qgenerateglow)
2790 skinframe->qgenerateglow = false;
2791 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
2796 skinframe->qgeneratebase = false;
2797 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
2798 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
2799 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
2803 skinframe->qgeneratemerged = false;
2804 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
2807 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
2809 Mem_Free(skinframe->qpixels);
2810 skinframe->qpixels = NULL;
2814 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)
2817 skinframe_t *skinframe;
2819 if (cls.state == ca_dedicated)
2822 // if already loaded just return it, otherwise make a new skinframe
2823 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2824 if (skinframe && skinframe->base)
2827 skinframe->stain = NULL;
2828 skinframe->merged = NULL;
2829 skinframe->base = r_texture_notexture;
2830 skinframe->pants = NULL;
2831 skinframe->shirt = NULL;
2832 skinframe->nmap = r_texture_blanknormalmap;
2833 skinframe->gloss = NULL;
2834 skinframe->glow = NULL;
2835 skinframe->fog = NULL;
2836 skinframe->hasalpha = false;
2838 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2842 if (developer_loading.integer)
2843 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2845 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
2846 if (textureflags & TEXF_ALPHA)
2848 for (i = 0;i < width * height;i++)
2850 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
2852 skinframe->hasalpha = true;
2856 if (r_loadfog && skinframe->hasalpha)
2857 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
2860 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2861 //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]);
2866 skinframe_t *R_SkinFrame_LoadMissing(void)
2868 skinframe_t *skinframe;
2870 if (cls.state == ca_dedicated)
2873 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2874 skinframe->stain = NULL;
2875 skinframe->merged = NULL;
2876 skinframe->base = r_texture_notexture;
2877 skinframe->pants = NULL;
2878 skinframe->shirt = NULL;
2879 skinframe->nmap = r_texture_blanknormalmap;
2880 skinframe->gloss = NULL;
2881 skinframe->glow = NULL;
2882 skinframe->fog = NULL;
2883 skinframe->hasalpha = false;
2885 skinframe->avgcolor[0] = rand() / RAND_MAX;
2886 skinframe->avgcolor[1] = rand() / RAND_MAX;
2887 skinframe->avgcolor[2] = rand() / RAND_MAX;
2888 skinframe->avgcolor[3] = 1;
2893 void R_Main_FreeViewCache(void)
2895 if (r_refdef.viewcache.entityvisible)
2896 Mem_Free(r_refdef.viewcache.entityvisible);
2897 if (r_refdef.viewcache.world_pvsbits)
2898 Mem_Free(r_refdef.viewcache.world_pvsbits);
2899 if (r_refdef.viewcache.world_leafvisible)
2900 Mem_Free(r_refdef.viewcache.world_leafvisible);
2901 if (r_refdef.viewcache.world_surfacevisible)
2902 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2903 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2906 void R_Main_ResizeViewCache(void)
2908 int numentities = r_refdef.scene.numentities;
2909 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
2910 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
2911 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
2912 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
2913 if (r_refdef.viewcache.maxentities < numentities)
2915 r_refdef.viewcache.maxentities = numentities;
2916 if (r_refdef.viewcache.entityvisible)
2917 Mem_Free(r_refdef.viewcache.entityvisible);
2918 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
2920 if (r_refdef.viewcache.world_numclusters != numclusters)
2922 r_refdef.viewcache.world_numclusters = numclusters;
2923 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
2924 if (r_refdef.viewcache.world_pvsbits)
2925 Mem_Free(r_refdef.viewcache.world_pvsbits);
2926 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
2928 if (r_refdef.viewcache.world_numleafs != numleafs)
2930 r_refdef.viewcache.world_numleafs = numleafs;
2931 if (r_refdef.viewcache.world_leafvisible)
2932 Mem_Free(r_refdef.viewcache.world_leafvisible);
2933 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
2935 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
2937 r_refdef.viewcache.world_numsurfaces = numsurfaces;
2938 if (r_refdef.viewcache.world_surfacevisible)
2939 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2940 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
2944 void gl_main_start(void)
2946 r_loadnormalmap = r_loadgloss = vid.support.arb_texture_env_dot3 || vid.support.arb_fragment_shader;
2951 memset(r_queries, 0, sizeof(r_queries));
2953 r_qwskincache = NULL;
2954 r_qwskincache_size = 0;
2956 // set up r_skinframe loading system for textures
2957 memset(&r_skinframe, 0, sizeof(r_skinframe));
2958 r_skinframe.loadsequence = 1;
2959 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2961 r_main_texturepool = R_AllocTexturePool();
2962 R_BuildBlankTextures();
2964 if (vid.support.arb_texture_cube_map)
2967 R_BuildNormalizationCube();
2969 r_texture_fogattenuation = NULL;
2970 r_texture_gammaramps = NULL;
2971 //r_texture_fogintensity = NULL;
2972 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2973 memset(&r_waterstate, 0, sizeof(r_waterstate));
2974 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2975 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2976 memset(&r_svbsp, 0, sizeof (r_svbsp));
2978 r_refdef.fogmasktable_density = 0;
2981 extern rtexture_t *loadingscreentexture;
2982 void gl_main_shutdown(void)
2984 R_Main_FreeViewCache();
2987 qglDeleteQueriesARB(r_maxqueries, r_queries);
2991 memset(r_queries, 0, sizeof(r_queries));
2993 r_qwskincache = NULL;
2994 r_qwskincache_size = 0;
2996 // clear out the r_skinframe state
2997 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2998 memset(&r_skinframe, 0, sizeof(r_skinframe));
3001 Mem_Free(r_svbsp.nodes);
3002 memset(&r_svbsp, 0, sizeof (r_svbsp));
3003 R_FreeTexturePool(&r_main_texturepool);
3004 loadingscreentexture = NULL;
3005 r_texture_blanknormalmap = NULL;
3006 r_texture_white = NULL;
3007 r_texture_grey128 = NULL;
3008 r_texture_black = NULL;
3009 r_texture_whitecube = NULL;
3010 r_texture_normalizationcube = NULL;
3011 r_texture_fogattenuation = NULL;
3012 r_texture_gammaramps = NULL;
3013 //r_texture_fogintensity = NULL;
3014 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3015 memset(&r_waterstate, 0, sizeof(r_waterstate));
3019 extern void CL_ParseEntityLump(char *entitystring);
3020 void gl_main_newmap(void)
3022 // FIXME: move this code to client
3024 char *entities, entname[MAX_QPATH];
3026 Mem_Free(r_qwskincache);
3027 r_qwskincache = NULL;
3028 r_qwskincache_size = 0;
3031 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
3032 l = (int)strlen(entname) - 4;
3033 if (l >= 0 && !strcmp(entname + l, ".bsp"))
3035 memcpy(entname + l, ".ent", 5);
3036 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3038 CL_ParseEntityLump(entities);
3043 if (cl.worldmodel->brush.entities)
3044 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3046 R_Main_FreeViewCache();
3049 void GL_Main_Init(void)
3051 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3053 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3054 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3055 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3056 if (gamemode == GAME_NEHAHRA)
3058 Cvar_RegisterVariable (&gl_fogenable);
3059 Cvar_RegisterVariable (&gl_fogdensity);
3060 Cvar_RegisterVariable (&gl_fogred);
3061 Cvar_RegisterVariable (&gl_foggreen);
3062 Cvar_RegisterVariable (&gl_fogblue);
3063 Cvar_RegisterVariable (&gl_fogstart);
3064 Cvar_RegisterVariable (&gl_fogend);
3065 Cvar_RegisterVariable (&gl_skyclip);
3067 Cvar_RegisterVariable(&r_motionblur);
3068 Cvar_RegisterVariable(&r_motionblur_maxblur);
3069 Cvar_RegisterVariable(&r_motionblur_bmin);
3070 Cvar_RegisterVariable(&r_motionblur_vmin);
3071 Cvar_RegisterVariable(&r_motionblur_vmax);
3072 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3073 Cvar_RegisterVariable(&r_motionblur_randomize);
3074 Cvar_RegisterVariable(&r_damageblur);
3075 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3076 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3077 Cvar_RegisterVariable(&r_equalize_entities_by);
3078 Cvar_RegisterVariable(&r_equalize_entities_to);
3079 Cvar_RegisterVariable(&r_animcache);
3080 Cvar_RegisterVariable(&r_depthfirst);
3081 Cvar_RegisterVariable(&r_useinfinitefarclip);
3082 Cvar_RegisterVariable(&r_farclip_base);
3083 Cvar_RegisterVariable(&r_farclip_world);
3084 Cvar_RegisterVariable(&r_nearclip);
3085 Cvar_RegisterVariable(&r_showbboxes);
3086 Cvar_RegisterVariable(&r_showsurfaces);
3087 Cvar_RegisterVariable(&r_showtris);
3088 Cvar_RegisterVariable(&r_shownormals);
3089 Cvar_RegisterVariable(&r_showlighting);
3090 Cvar_RegisterVariable(&r_showshadowvolumes);
3091 Cvar_RegisterVariable(&r_showcollisionbrushes);
3092 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3093 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3094 Cvar_RegisterVariable(&r_showdisabledepthtest);
3095 Cvar_RegisterVariable(&r_drawportals);
3096 Cvar_RegisterVariable(&r_drawentities);
3097 Cvar_RegisterVariable(&r_cullentities_trace);
3098 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3099 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3100 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3101 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3102 Cvar_RegisterVariable(&r_drawviewmodel);
3103 Cvar_RegisterVariable(&r_speeds);
3104 Cvar_RegisterVariable(&r_fullbrights);
3105 Cvar_RegisterVariable(&r_wateralpha);
3106 Cvar_RegisterVariable(&r_dynamic);
3107 Cvar_RegisterVariable(&r_fullbright);
3108 Cvar_RegisterVariable(&r_shadows);
3109 Cvar_RegisterVariable(&r_shadows_darken);
3110 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3111 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3112 Cvar_RegisterVariable(&r_shadows_throwdistance);
3113 Cvar_RegisterVariable(&r_shadows_throwdirection);
3114 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3115 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3116 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3117 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3118 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3119 Cvar_RegisterVariable(&r_fog_exp2);
3120 Cvar_RegisterVariable(&r_drawfog);
3121 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3122 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3123 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3124 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3125 Cvar_RegisterVariable(&r_glsl_postprocess);
3126 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3127 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3128 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3129 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3130 Cvar_RegisterVariable(&r_water);
3131 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3132 Cvar_RegisterVariable(&r_water_clippingplanebias);
3133 Cvar_RegisterVariable(&r_water_refractdistort);
3134 Cvar_RegisterVariable(&r_water_reflectdistort);
3135 Cvar_RegisterVariable(&r_lerpsprites);
3136 Cvar_RegisterVariable(&r_lerpmodels);
3137 Cvar_RegisterVariable(&r_lerplightstyles);
3138 Cvar_RegisterVariable(&r_waterscroll);
3139 Cvar_RegisterVariable(&r_bloom);
3140 Cvar_RegisterVariable(&r_bloom_colorscale);
3141 Cvar_RegisterVariable(&r_bloom_brighten);
3142 Cvar_RegisterVariable(&r_bloom_blur);
3143 Cvar_RegisterVariable(&r_bloom_resolution);
3144 Cvar_RegisterVariable(&r_bloom_colorexponent);
3145 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3146 Cvar_RegisterVariable(&r_hdr);
3147 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3148 Cvar_RegisterVariable(&r_hdr_glowintensity);
3149 Cvar_RegisterVariable(&r_hdr_range);
3150 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3151 Cvar_RegisterVariable(&developer_texturelogging);
3152 Cvar_RegisterVariable(&gl_lightmaps);
3153 Cvar_RegisterVariable(&r_test);
3154 Cvar_RegisterVariable(&r_batchmode);
3155 Cvar_RegisterVariable(&r_glsl_saturation);
3156 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3157 Cvar_SetValue("r_fullbrights", 0);
3158 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3160 Cvar_RegisterVariable(&r_track_sprites);
3161 Cvar_RegisterVariable(&r_track_sprites_flags);
3162 Cvar_RegisterVariable(&r_track_sprites_scalew);
3163 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3166 extern void R_Textures_Init(void);
3167 extern void GL_Draw_Init(void);
3168 extern void GL_Main_Init(void);
3169 extern void R_Shadow_Init(void);
3170 extern void R_Sky_Init(void);
3171 extern void GL_Surf_Init(void);
3172 extern void R_Particles_Init(void);
3173 extern void R_Explosion_Init(void);
3174 extern void gl_backend_init(void);
3175 extern void Sbar_Init(void);
3176 extern void R_LightningBeams_Init(void);
3177 extern void Mod_RenderInit(void);
3179 void Render_Init(void)
3191 R_LightningBeams_Init();
3200 extern char *ENGINE_EXTENSIONS;
3203 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3204 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3205 gl_version = (const char *)qglGetString(GL_VERSION);
3206 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3210 if (!gl_platformextensions)
3211 gl_platformextensions = "";
3213 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3214 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3215 Con_Printf("GL_VERSION: %s\n", gl_version);
3216 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3217 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3219 VID_CheckExtensions();
3221 // LordHavoc: report supported extensions
3222 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3224 // clear to black (loading plaque will be seen over this)
3226 qglClearColor(0,0,0,1);CHECKGLERROR
3227 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3230 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3234 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3236 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3239 p = r_refdef.view.frustum + i;
3244 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3248 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3252 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3256 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3260 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3264 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3268 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3272 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3280 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3284 for (i = 0;i < numplanes;i++)
3291 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3295 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3299 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3303 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3307 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3311 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3315 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3319 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3327 //==================================================================================
3329 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3332 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3333 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3334 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3337 typedef struct r_animcache_entity_s
3344 qboolean wantnormals;
3345 qboolean wanttangents;
3347 r_animcache_entity_t;
3349 typedef struct r_animcache_s
3351 r_animcache_entity_t entity[MAX_EDICTS];
3357 static r_animcache_t r_animcachestate;
3359 void R_AnimCache_Free(void)
3362 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3364 r_animcachestate.entity[idx].maxvertices = 0;
3365 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3366 r_animcachestate.entity[idx].vertex3f = NULL;
3367 r_animcachestate.entity[idx].normal3f = NULL;
3368 r_animcachestate.entity[idx].svector3f = NULL;
3369 r_animcachestate.entity[idx].tvector3f = NULL;
3371 r_animcachestate.currentindex = 0;
3372 r_animcachestate.maxindex = 0;
3375 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3379 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3381 if (cache->maxvertices >= numvertices)
3384 // Release existing memory
3385 if (cache->vertex3f)
3386 Mem_Free(cache->vertex3f);
3388 // Pad by 1024 verts
3389 cache->maxvertices = (numvertices + 1023) & ~1023;
3390 arraySize = cache->maxvertices * 3;
3392 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3393 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3394 r_animcachestate.entity[cacheIdx].vertex3f = base;
3395 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3396 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3397 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3399 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3402 void R_AnimCache_NewFrame(void)
3406 if (r_animcache.integer && r_drawentities.integer)
3407 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3408 else if (r_animcachestate.maxindex)
3411 r_animcachestate.currentindex = 0;
3413 for (i = 0;i < r_refdef.scene.numentities;i++)
3414 r_refdef.scene.entities[i]->animcacheindex = -1;
3417 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3419 dp_model_t *model = ent->model;
3420 r_animcache_entity_t *c;
3421 // see if it's already cached this frame
3422 if (ent->animcacheindex >= 0)
3424 // add normals/tangents if needed
3425 c = r_animcachestate.entity + ent->animcacheindex;
3427 wantnormals = false;
3428 if (c->wanttangents)
3429 wanttangents = false;
3430 if (wantnormals || wanttangents)
3431 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3435 // see if this ent is worth caching
3436 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3438 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3440 // assign it a cache entry and make sure the arrays are big enough
3441 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3442 ent->animcacheindex = r_animcachestate.currentindex++;
3443 c = r_animcachestate.entity + ent->animcacheindex;
3444 c->wantnormals = wantnormals;
3445 c->wanttangents = wanttangents;
3446 model->AnimateVertices(model, ent->frameblend, ent->skeleton, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3451 void R_AnimCache_CacheVisibleEntities(void)
3454 qboolean wantnormals;
3455 qboolean wanttangents;
3457 if (!r_animcachestate.maxindex)
3460 wantnormals = !r_showsurfaces.integer;
3461 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3463 // TODO: thread this?
3465 for (i = 0;i < r_refdef.scene.numentities;i++)
3467 if (!r_refdef.viewcache.entityvisible[i])
3469 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3473 //==================================================================================
3475 static void R_View_UpdateEntityLighting (void)
3478 entity_render_t *ent;
3479 vec3_t tempdiffusenormal, avg;
3480 vec_t f, fa, fd, fdd;
3482 for (i = 0;i < r_refdef.scene.numentities;i++)
3484 ent = r_refdef.scene.entities[i];
3486 // skip unseen models
3487 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3491 if (ent->model && ent->model->brush.num_leafs)
3493 // TODO: use modellight for r_ambient settings on world?
3494 VectorSet(ent->modellight_ambient, 0, 0, 0);
3495 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3496 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3500 // fetch the lighting from the worldmodel data
3501 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));
3502 VectorClear(ent->modellight_diffuse);
3503 VectorClear(tempdiffusenormal);
3504 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3507 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3508 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3509 if(ent->flags & RENDER_EQUALIZE)
3511 // first fix up ambient lighting...
3512 if(r_equalize_entities_minambient.value > 0)
3514 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3517 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3518 if(fa < r_equalize_entities_minambient.value * fd)
3521 // fa'/fd' = minambient
3522 // fa'+0.25*fd' = fa+0.25*fd
3524 // fa' = fd' * minambient
3525 // fd'*(0.25+minambient) = fa+0.25*fd
3527 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3528 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3530 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3531 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
3532 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3533 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3538 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3540 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3541 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3544 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3545 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3546 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3552 VectorSet(ent->modellight_ambient, 1, 1, 1);
3554 // move the light direction into modelspace coordinates for lighting code
3555 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3556 if(VectorLength2(ent->modellight_lightdir) == 0)
3557 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3558 VectorNormalize(ent->modellight_lightdir);
3562 #define MAX_LINEOFSIGHTTRACES 64
3564 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3567 vec3_t boxmins, boxmaxs;
3570 dp_model_t *model = r_refdef.scene.worldmodel;
3572 if (!model || !model->brush.TraceLineOfSight)
3575 // expand the box a little
3576 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3577 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3578 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3579 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3580 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3581 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3584 VectorCopy(eye, start);
3585 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3586 if (model->brush.TraceLineOfSight(model, start, end))
3589 // try various random positions
3590 for (i = 0;i < numsamples;i++)
3592 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3593 if (model->brush.TraceLineOfSight(model, start, end))
3601 static void R_View_UpdateEntityVisible (void)
3606 entity_render_t *ent;
3608 if (!r_drawentities.integer)
3611 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3612 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3614 // worldmodel can check visibility
3615 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3616 for (i = 0;i < r_refdef.scene.numentities;i++)
3618 ent = r_refdef.scene.entities[i];
3619 if (!(ent->flags & renderimask))
3620 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)))
3621 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))
3622 r_refdef.viewcache.entityvisible[i] = true;
3624 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3626 for (i = 0;i < r_refdef.scene.numentities;i++)
3628 ent = r_refdef.scene.entities[i];
3629 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3631 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3633 continue; // temp entities do pvs only
3634 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3635 ent->last_trace_visibility = realtime;
3636 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3637 r_refdef.viewcache.entityvisible[i] = 0;
3644 // no worldmodel or it can't check visibility
3645 for (i = 0;i < r_refdef.scene.numentities;i++)
3647 ent = r_refdef.scene.entities[i];
3648 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));
3653 /// only used if skyrendermasked, and normally returns false
3654 int R_DrawBrushModelsSky (void)
3657 entity_render_t *ent;
3659 if (!r_drawentities.integer)
3663 for (i = 0;i < r_refdef.scene.numentities;i++)
3665 if (!r_refdef.viewcache.entityvisible[i])
3667 ent = r_refdef.scene.entities[i];
3668 if (!ent->model || !ent->model->DrawSky)
3670 ent->model->DrawSky(ent);
3676 static void R_DrawNoModel(entity_render_t *ent);
3677 static void R_DrawModels(void)
3680 entity_render_t *ent;
3682 if (!r_drawentities.integer)
3685 for (i = 0;i < r_refdef.scene.numentities;i++)
3687 if (!r_refdef.viewcache.entityvisible[i])
3689 ent = r_refdef.scene.entities[i];
3690 r_refdef.stats.entities++;
3691 if (ent->model && ent->model->Draw != NULL)
3692 ent->model->Draw(ent);
3698 static void R_DrawModelsDepth(void)
3701 entity_render_t *ent;
3703 if (!r_drawentities.integer)
3706 for (i = 0;i < r_refdef.scene.numentities;i++)
3708 if (!r_refdef.viewcache.entityvisible[i])
3710 ent = r_refdef.scene.entities[i];
3711 if (ent->model && ent->model->DrawDepth != NULL)
3712 ent->model->DrawDepth(ent);
3716 static void R_DrawModelsDebug(void)
3719 entity_render_t *ent;
3721 if (!r_drawentities.integer)
3724 for (i = 0;i < r_refdef.scene.numentities;i++)
3726 if (!r_refdef.viewcache.entityvisible[i])
3728 ent = r_refdef.scene.entities[i];
3729 if (ent->model && ent->model->DrawDebug != NULL)
3730 ent->model->DrawDebug(ent);
3734 static void R_DrawModelsAddWaterPlanes(void)
3737 entity_render_t *ent;
3739 if (!r_drawentities.integer)
3742 for (i = 0;i < r_refdef.scene.numentities;i++)
3744 if (!r_refdef.viewcache.entityvisible[i])
3746 ent = r_refdef.scene.entities[i];
3747 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3748 ent->model->DrawAddWaterPlanes(ent);
3752 static void R_View_SetFrustum(void)
3755 double slopex, slopey;
3756 vec3_t forward, left, up, origin;
3758 // we can't trust r_refdef.view.forward and friends in reflected scenes
3759 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3762 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3763 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3764 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3765 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3766 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3767 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3768 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3769 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3770 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3771 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3772 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3773 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3777 zNear = r_refdef.nearclip;
3778 nudge = 1.0 - 1.0 / (1<<23);
3779 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3780 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3781 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3782 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3783 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3784 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3785 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3786 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3792 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3793 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3794 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3795 r_refdef.view.frustum[0].dist = m[15] - m[12];
3797 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3798 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3799 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3800 r_refdef.view.frustum[1].dist = m[15] + m[12];
3802 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3803 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3804 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3805 r_refdef.view.frustum[2].dist = m[15] - m[13];
3807 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3808 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3809 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3810 r_refdef.view.frustum[3].dist = m[15] + m[13];
3812 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3813 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3814 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3815 r_refdef.view.frustum[4].dist = m[15] - m[14];
3817 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3818 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3819 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3820 r_refdef.view.frustum[5].dist = m[15] + m[14];
3823 if (r_refdef.view.useperspective)
3825 slopex = 1.0 / r_refdef.view.frustum_x;
3826 slopey = 1.0 / r_refdef.view.frustum_y;
3827 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3828 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3829 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3830 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3831 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3833 // Leaving those out was a mistake, those were in the old code, and they
3834 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3835 // I couldn't reproduce it after adding those normalizations. --blub
3836 VectorNormalize(r_refdef.view.frustum[0].normal);
3837 VectorNormalize(r_refdef.view.frustum[1].normal);
3838 VectorNormalize(r_refdef.view.frustum[2].normal);
3839 VectorNormalize(r_refdef.view.frustum[3].normal);
3841 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3842 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]);
3843 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]);
3844 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]);
3845 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]);
3847 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3848 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3849 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3850 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3851 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3855 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3856 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3857 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3858 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3859 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3860 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3861 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3862 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3863 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3864 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3866 r_refdef.view.numfrustumplanes = 5;
3868 if (r_refdef.view.useclipplane)
3870 r_refdef.view.numfrustumplanes = 6;
3871 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3874 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3875 PlaneClassify(r_refdef.view.frustum + i);
3877 // LordHavoc: note to all quake engine coders, Quake had a special case
3878 // for 90 degrees which assumed a square view (wrong), so I removed it,
3879 // Quake2 has it disabled as well.
3881 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3882 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3883 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3884 //PlaneClassify(&frustum[0]);
3886 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3887 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3888 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3889 //PlaneClassify(&frustum[1]);
3891 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3892 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3893 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3894 //PlaneClassify(&frustum[2]);
3896 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3897 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3898 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3899 //PlaneClassify(&frustum[3]);
3902 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3903 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3904 //PlaneClassify(&frustum[4]);
3907 void R_View_Update(void)
3909 R_Main_ResizeViewCache();
3910 R_View_SetFrustum();
3911 R_View_WorldVisibility(r_refdef.view.useclipplane);
3912 R_View_UpdateEntityVisible();
3913 R_View_UpdateEntityLighting();
3916 void R_SetupView(qboolean allowwaterclippingplane)
3918 const double *customclipplane = NULL;
3920 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3922 // LordHavoc: couldn't figure out how to make this approach the
3923 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3924 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3925 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3926 dist = r_refdef.view.clipplane.dist;
3927 plane[0] = r_refdef.view.clipplane.normal[0];
3928 plane[1] = r_refdef.view.clipplane.normal[1];
3929 plane[2] = r_refdef.view.clipplane.normal[2];
3931 customclipplane = plane;
3934 if (!r_refdef.view.useperspective)
3935 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);
3936 else if (vid.stencil && r_useinfinitefarclip.integer)
3937 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);
3939 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);
3940 R_SetViewport(&r_refdef.view.viewport);
3943 void R_ResetViewRendering2D(void)
3945 r_viewport_t viewport;
3948 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3949 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);
3950 R_SetViewport(&viewport);
3951 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3952 GL_Color(1, 1, 1, 1);
3953 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3954 GL_BlendFunc(GL_ONE, GL_ZERO);
3955 GL_AlphaTest(false);
3956 GL_ScissorTest(false);
3957 GL_DepthMask(false);
3958 GL_DepthRange(0, 1);
3959 GL_DepthTest(false);
3960 R_Mesh_Matrix(&identitymatrix);
3961 R_Mesh_ResetTextureState();
3962 GL_PolygonOffset(0, 0);
3963 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3964 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3965 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3966 qglStencilMask(~0);CHECKGLERROR
3967 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3968 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3969 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3970 R_SetupGenericShader(true);
3973 void R_ResetViewRendering3D(void)
3978 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3979 GL_Color(1, 1, 1, 1);
3980 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3981 GL_BlendFunc(GL_ONE, GL_ZERO);
3982 GL_AlphaTest(false);
3983 GL_ScissorTest(true);
3985 GL_DepthRange(0, 1);
3987 R_Mesh_Matrix(&identitymatrix);
3988 R_Mesh_ResetTextureState();
3989 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3990 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3991 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3992 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3993 qglStencilMask(~0);CHECKGLERROR
3994 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3995 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3996 GL_CullFace(r_refdef.view.cullface_back);
3997 R_SetupGenericShader(true);
4000 void R_RenderScene(void);
4001 void R_RenderWaterPlanes(void);
4003 static void R_Water_StartFrame(void)
4006 int waterwidth, waterheight, texturewidth, textureheight;
4007 r_waterstate_waterplane_t *p;
4009 // set waterwidth and waterheight to the water resolution that will be
4010 // used (often less than the screen resolution for faster rendering)
4011 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
4012 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
4014 // calculate desired texture sizes
4015 // can't use water if the card does not support the texture size
4016 if (!r_water.integer || !r_glsl.integer || !vid.support.arb_fragment_shader || waterwidth > (int)vid.maxtexturesize_2d || waterheight > (int)vid.maxtexturesize_2d || r_showsurfaces.integer)
4017 texturewidth = textureheight = waterwidth = waterheight = 0;
4018 else if (vid.support.arb_texture_non_power_of_two)
4020 texturewidth = waterwidth;
4021 textureheight = waterheight;
4025 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4026 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4029 // allocate textures as needed
4030 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4032 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4033 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4035 if (p->texture_refraction)
4036 R_FreeTexture(p->texture_refraction);
4037 p->texture_refraction = NULL;
4038 if (p->texture_reflection)
4039 R_FreeTexture(p->texture_reflection);
4040 p->texture_reflection = NULL;
4042 memset(&r_waterstate, 0, sizeof(r_waterstate));
4043 r_waterstate.texturewidth = texturewidth;
4044 r_waterstate.textureheight = textureheight;
4047 if (r_waterstate.texturewidth)
4049 r_waterstate.enabled = true;
4051 // when doing a reduced render (HDR) we want to use a smaller area
4052 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4053 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4055 // set up variables that will be used in shader setup
4056 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4057 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4058 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4059 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4062 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4063 r_waterstate.numwaterplanes = 0;
4066 void R_Water_AddWaterPlane(msurface_t *surface)
4068 int triangleindex, planeindex;
4074 r_waterstate_waterplane_t *p;
4075 texture_t *t = R_GetCurrentTexture(surface->texture);
4076 // just use the first triangle with a valid normal for any decisions
4077 VectorClear(normal);
4078 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4080 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4081 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4082 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4083 TriangleNormal(vert[0], vert[1], vert[2], normal);
4084 if (VectorLength2(normal) >= 0.001)
4088 VectorCopy(normal, plane.normal);
4089 VectorNormalize(plane.normal);
4090 plane.dist = DotProduct(vert[0], plane.normal);
4091 PlaneClassify(&plane);
4092 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4094 // skip backfaces (except if nocullface is set)
4095 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4097 VectorNegate(plane.normal, plane.normal);
4099 PlaneClassify(&plane);
4103 // find a matching plane if there is one
4104 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4105 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4107 if (planeindex >= r_waterstate.maxwaterplanes)
4108 return; // nothing we can do, out of planes
4110 // if this triangle does not fit any known plane rendered this frame, add one
4111 if (planeindex >= r_waterstate.numwaterplanes)
4113 // store the new plane
4114 r_waterstate.numwaterplanes++;
4116 // clear materialflags and pvs
4117 p->materialflags = 0;
4118 p->pvsvalid = false;
4120 // merge this surface's materialflags into the waterplane
4121 p->materialflags |= t->currentmaterialflags;
4122 // merge this surface's PVS into the waterplane
4123 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4124 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4125 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4127 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4132 static void R_Water_ProcessPlanes(void)
4134 r_refdef_view_t originalview;
4135 r_refdef_view_t myview;
4137 r_waterstate_waterplane_t *p;
4139 originalview = r_refdef.view;
4141 // make sure enough textures are allocated
4142 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4144 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4146 if (!p->texture_refraction)
4147 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);
4148 if (!p->texture_refraction)
4152 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4154 if (!p->texture_reflection)
4155 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);
4156 if (!p->texture_reflection)
4162 r_refdef.view = originalview;
4163 r_refdef.view.showdebug = false;
4164 r_refdef.view.width = r_waterstate.waterwidth;
4165 r_refdef.view.height = r_waterstate.waterheight;
4166 r_refdef.view.useclipplane = true;
4167 myview = r_refdef.view;
4168 r_waterstate.renderingscene = true;
4169 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4171 // render the normal view scene and copy into texture
4172 // (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)
4173 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4175 r_refdef.view = myview;
4176 r_refdef.view.clipplane = p->plane;
4177 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4178 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4179 PlaneClassify(&r_refdef.view.clipplane);
4181 R_ResetViewRendering3D();
4182 R_ClearScreen(r_refdef.fogenabled);
4186 // copy view into the screen texture
4187 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4188 GL_ActiveTexture(0);
4190 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
4193 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4195 r_refdef.view = myview;
4196 // render reflected scene and copy into texture
4197 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4198 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4199 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4200 r_refdef.view.clipplane = p->plane;
4201 // reverse the cullface settings for this render
4202 r_refdef.view.cullface_front = GL_FRONT;
4203 r_refdef.view.cullface_back = GL_BACK;
4204 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4206 r_refdef.view.usecustompvs = true;
4208 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4210 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4213 R_ResetViewRendering3D();
4214 R_ClearScreen(r_refdef.fogenabled);
4218 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4219 GL_ActiveTexture(0);
4221 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
4224 r_waterstate.renderingscene = false;
4225 r_refdef.view = originalview;
4226 R_ResetViewRendering3D();
4227 R_ClearScreen(r_refdef.fogenabled);
4231 r_refdef.view = originalview;
4232 r_waterstate.renderingscene = false;
4233 Cvar_SetValueQuick(&r_water, 0);
4234 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4238 void R_Bloom_StartFrame(void)
4240 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4242 // set bloomwidth and bloomheight to the bloom resolution that will be
4243 // used (often less than the screen resolution for faster rendering)
4244 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4245 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4246 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4247 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
4248 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
4250 // calculate desired texture sizes
4251 if (vid.support.arb_texture_non_power_of_two)
4253 screentexturewidth = r_refdef.view.width;
4254 screentextureheight = r_refdef.view.height;
4255 bloomtexturewidth = r_bloomstate.bloomwidth;
4256 bloomtextureheight = r_bloomstate.bloomheight;
4260 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4261 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4262 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4263 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4266 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
4268 Cvar_SetValueQuick(&r_hdr, 0);
4269 Cvar_SetValueQuick(&r_bloom, 0);
4270 Cvar_SetValueQuick(&r_motionblur, 0);
4271 Cvar_SetValueQuick(&r_damageblur, 0);
4274 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)))
4275 screentexturewidth = screentextureheight = 0;
4276 if (!r_hdr.integer && !r_bloom.integer)
4277 bloomtexturewidth = bloomtextureheight = 0;
4279 // allocate textures as needed
4280 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4282 if (r_bloomstate.texture_screen)
4283 R_FreeTexture(r_bloomstate.texture_screen);
4284 r_bloomstate.texture_screen = NULL;
4285 r_bloomstate.screentexturewidth = screentexturewidth;
4286 r_bloomstate.screentextureheight = screentextureheight;
4287 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4288 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);
4290 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4292 if (r_bloomstate.texture_bloom)
4293 R_FreeTexture(r_bloomstate.texture_bloom);
4294 r_bloomstate.texture_bloom = NULL;
4295 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4296 r_bloomstate.bloomtextureheight = bloomtextureheight;
4297 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4298 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);
4301 // when doing a reduced render (HDR) we want to use a smaller area
4302 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4303 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4304 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4305 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4306 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4308 // set up a texcoord array for the full resolution screen image
4309 // (we have to keep this around to copy back during final render)
4310 r_bloomstate.screentexcoord2f[0] = 0;
4311 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4312 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4313 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4314 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4315 r_bloomstate.screentexcoord2f[5] = 0;
4316 r_bloomstate.screentexcoord2f[6] = 0;
4317 r_bloomstate.screentexcoord2f[7] = 0;
4319 // set up a texcoord array for the reduced resolution bloom image
4320 // (which will be additive blended over the screen image)
4321 r_bloomstate.bloomtexcoord2f[0] = 0;
4322 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4323 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4324 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4325 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4326 r_bloomstate.bloomtexcoord2f[5] = 0;
4327 r_bloomstate.bloomtexcoord2f[6] = 0;
4328 r_bloomstate.bloomtexcoord2f[7] = 0;
4330 if (r_hdr.integer || r_bloom.integer)
4332 r_bloomstate.enabled = true;
4333 r_bloomstate.hdr = r_hdr.integer != 0;
4336 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);
4339 void R_Bloom_CopyBloomTexture(float colorscale)
4341 r_refdef.stats.bloom++;
4343 // scale down screen texture to the bloom texture size
4345 R_SetViewport(&r_bloomstate.viewport);
4346 GL_BlendFunc(GL_ONE, GL_ZERO);
4347 GL_Color(colorscale, colorscale, colorscale, 1);
4348 // TODO: optimize with multitexture or GLSL
4349 R_SetupGenericShader(true);
4350 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4351 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4352 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4353 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4355 // we now have a bloom image in the framebuffer
4356 // copy it into the bloom image texture for later processing
4357 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4358 GL_ActiveTexture(0);
4360 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4361 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4364 void R_Bloom_CopyHDRTexture(void)
4366 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4367 GL_ActiveTexture(0);
4369 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
4370 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4373 void R_Bloom_MakeTexture(void)
4376 float xoffset, yoffset, r, brighten;
4378 r_refdef.stats.bloom++;
4380 R_ResetViewRendering2D();
4381 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4382 R_Mesh_ColorPointer(NULL, 0, 0);
4383 R_SetupGenericShader(true);
4385 // we have a bloom image in the framebuffer
4387 R_SetViewport(&r_bloomstate.viewport);
4389 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4392 r = bound(0, r_bloom_colorexponent.value / x, 1);
4393 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4394 GL_Color(r, r, r, 1);
4395 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4396 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4397 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4398 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4400 // copy the vertically blurred bloom view to a texture
4401 GL_ActiveTexture(0);
4403 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4404 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4407 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4408 brighten = r_bloom_brighten.value;
4410 brighten *= r_hdr_range.value;
4411 brighten = sqrt(brighten);
4413 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4414 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4415 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4417 for (dir = 0;dir < 2;dir++)
4419 // blend on at multiple vertical offsets to achieve a vertical blur
4420 // TODO: do offset blends using GLSL
4421 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4422 GL_BlendFunc(GL_ONE, GL_ZERO);
4423 for (x = -range;x <= range;x++)
4425 if (!dir){xoffset = 0;yoffset = x;}
4426 else {xoffset = x;yoffset = 0;}
4427 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4428 yoffset /= (float)r_bloomstate.bloomtextureheight;
4429 // compute a texcoord array with the specified x and y offset
4430 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4431 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4432 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4433 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4434 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4435 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4436 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4437 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4438 // this r value looks like a 'dot' particle, fading sharply to
4439 // black at the edges
4440 // (probably not realistic but looks good enough)
4441 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4442 //r = brighten/(range*2+1);
4443 r = brighten / (range * 2 + 1);
4445 r *= (1 - x*x/(float)(range*range));
4446 GL_Color(r, r, r, 1);
4447 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4448 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4449 GL_BlendFunc(GL_ONE, GL_ONE);
4452 // copy the vertically blurred bloom view to a texture
4453 GL_ActiveTexture(0);
4455 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4456 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4459 // apply subtract last
4460 // (just like it would be in a GLSL shader)
4461 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
4463 GL_BlendFunc(GL_ONE, GL_ZERO);
4464 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4465 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4466 GL_Color(1, 1, 1, 1);
4467 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4468 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4470 GL_BlendFunc(GL_ONE, GL_ONE);
4471 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4472 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4473 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4474 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4475 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4476 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4477 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4479 // copy the darkened bloom view to a texture
4480 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4481 GL_ActiveTexture(0);
4483 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4484 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4488 void R_HDR_RenderBloomTexture(void)
4490 int oldwidth, oldheight;
4491 float oldcolorscale;
4493 oldcolorscale = r_refdef.view.colorscale;
4494 oldwidth = r_refdef.view.width;
4495 oldheight = r_refdef.view.height;
4496 r_refdef.view.width = r_bloomstate.bloomwidth;
4497 r_refdef.view.height = r_bloomstate.bloomheight;
4499 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4500 // TODO: add exposure compensation features
4501 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4503 r_refdef.view.showdebug = false;
4504 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4506 R_ResetViewRendering3D();
4508 R_ClearScreen(r_refdef.fogenabled);
4509 if (r_timereport_active)
4510 R_TimeReport("HDRclear");
4513 if (r_timereport_active)
4514 R_TimeReport("visibility");
4516 // only do secondary renders with HDR if r_hdr is 2 or higher
4517 r_waterstate.numwaterplanes = 0;
4518 if (r_waterstate.enabled && r_hdr.integer >= 2)
4519 R_RenderWaterPlanes();
4521 r_refdef.view.showdebug = true;
4523 r_waterstate.numwaterplanes = 0;
4525 R_ResetViewRendering2D();
4527 R_Bloom_CopyHDRTexture();
4528 R_Bloom_MakeTexture();
4530 // restore the view settings
4531 r_refdef.view.width = oldwidth;
4532 r_refdef.view.height = oldheight;
4533 r_refdef.view.colorscale = oldcolorscale;
4535 R_ResetViewRendering3D();
4537 R_ClearScreen(r_refdef.fogenabled);
4538 if (r_timereport_active)
4539 R_TimeReport("viewclear");
4542 static void R_BlendView(void)
4544 if (r_bloomstate.texture_screen)
4546 // make sure the buffer is available
4547 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4549 R_ResetViewRendering2D();
4550 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4551 R_Mesh_ColorPointer(NULL, 0, 0);
4552 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4553 GL_ActiveTexture(0);CHECKGLERROR
4555 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4557 // declare variables
4559 static float avgspeed;
4561 speed = VectorLength(cl.movement_velocity);
4563 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4564 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4566 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4567 speed = bound(0, speed, 1);
4568 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4570 // calculate values into a standard alpha
4571 cl.motionbluralpha = 1 - exp(-
4573 (r_motionblur.value * speed / 80)
4575 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4578 max(0.0001, cl.time - cl.oldtime) // fps independent
4581 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4582 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4584 if (cl.motionbluralpha > 0)
4586 R_SetupGenericShader(true);
4587 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4588 GL_Color(1, 1, 1, cl.motionbluralpha);
4589 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4590 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4591 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4592 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4596 // copy view into the screen texture
4597 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
4598 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4601 if (r_glsl.integer && vid.support.arb_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4603 unsigned int permutation =
4604 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4605 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4606 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4607 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4608 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4610 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4612 // render simple bloom effect
4613 // copy the screen and shrink it and darken it for the bloom process
4614 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4615 // make the bloom texture
4616 R_Bloom_MakeTexture();
4619 R_ResetViewRendering2D();
4620 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4621 R_Mesh_ColorPointer(NULL, 0, 0);
4622 GL_Color(1, 1, 1, 1);
4623 GL_BlendFunc(GL_ONE, GL_ZERO);
4624 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4625 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4626 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4627 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4628 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4629 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4630 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4631 if (r_glsl_permutation->loc_TintColor >= 0)
4632 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4633 if (r_glsl_permutation->loc_ClientTime >= 0)
4634 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4635 if (r_glsl_permutation->loc_PixelSize >= 0)
4636 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4637 if (r_glsl_permutation->loc_UserVec1 >= 0)
4639 float a=0, b=0, c=0, d=0;
4640 #if _MSC_VER >= 1400
4641 #define sscanf sscanf_s
4643 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4644 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4646 if (r_glsl_permutation->loc_UserVec2 >= 0)
4648 float a=0, b=0, c=0, d=0;
4649 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4650 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4652 if (r_glsl_permutation->loc_UserVec3 >= 0)
4654 float a=0, b=0, c=0, d=0;
4655 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4656 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4658 if (r_glsl_permutation->loc_UserVec4 >= 0)
4660 float a=0, b=0, c=0, d=0;
4661 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4662 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4664 if (r_glsl_permutation->loc_Saturation >= 0)
4665 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4666 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4667 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4673 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4675 // render high dynamic range bloom effect
4676 // the bloom texture was made earlier this render, so we just need to
4677 // blend it onto the screen...
4678 R_ResetViewRendering2D();
4679 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4680 R_Mesh_ColorPointer(NULL, 0, 0);
4681 R_SetupGenericShader(true);
4682 GL_Color(1, 1, 1, 1);
4683 GL_BlendFunc(GL_ONE, GL_ONE);
4684 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4685 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4686 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4687 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4689 else if (r_bloomstate.texture_bloom)
4691 // render simple bloom effect
4692 // copy the screen and shrink it and darken it for the bloom process
4693 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4694 // make the bloom texture
4695 R_Bloom_MakeTexture();
4696 // put the original screen image back in place and blend the bloom
4698 R_ResetViewRendering2D();
4699 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4700 R_Mesh_ColorPointer(NULL, 0, 0);
4701 GL_Color(1, 1, 1, 1);
4702 GL_BlendFunc(GL_ONE, GL_ZERO);
4703 // do both in one pass if possible
4704 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4705 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4706 if (r_textureunits.integer >= 2 && gl_combine.integer)
4708 R_SetupGenericTwoTextureShader(GL_ADD);
4709 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4710 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4714 R_SetupGenericShader(true);
4715 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4716 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4717 // now blend on the bloom texture
4718 GL_BlendFunc(GL_ONE, GL_ONE);
4719 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4720 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4722 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4723 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4725 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4727 // apply a color tint to the whole view
4728 R_ResetViewRendering2D();
4729 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4730 R_Mesh_ColorPointer(NULL, 0, 0);
4731 R_SetupGenericShader(false);
4732 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4733 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4734 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4738 matrix4x4_t r_waterscrollmatrix;
4740 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4742 if (r_refdef.fog_density)
4744 r_refdef.fogcolor[0] = r_refdef.fog_red;
4745 r_refdef.fogcolor[1] = r_refdef.fog_green;
4746 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4748 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4749 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4750 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4751 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4755 VectorCopy(r_refdef.fogcolor, fogvec);
4756 // color.rgb *= ContrastBoost * SceneBrightness;
4757 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4758 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4759 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4760 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4765 void R_UpdateVariables(void)
4769 r_refdef.scene.ambient = r_ambient.value;
4771 r_refdef.farclip = r_farclip_base.value;
4772 if (r_refdef.scene.worldmodel)
4773 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
4774 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4776 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4777 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4778 r_refdef.polygonfactor = 0;
4779 r_refdef.polygonoffset = 0;
4780 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4781 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4783 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4784 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
4785 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4786 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
4787 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4788 if (r_showsurfaces.integer)
4790 r_refdef.scene.rtworld = false;
4791 r_refdef.scene.rtworldshadows = false;
4792 r_refdef.scene.rtdlight = false;
4793 r_refdef.scene.rtdlightshadows = false;
4794 r_refdef.lightmapintensity = 0;
4797 if (gamemode == GAME_NEHAHRA)
4799 if (gl_fogenable.integer)
4801 r_refdef.oldgl_fogenable = true;
4802 r_refdef.fog_density = gl_fogdensity.value;
4803 r_refdef.fog_red = gl_fogred.value;
4804 r_refdef.fog_green = gl_foggreen.value;
4805 r_refdef.fog_blue = gl_fogblue.value;
4806 r_refdef.fog_alpha = 1;
4807 r_refdef.fog_start = 0;
4808 r_refdef.fog_end = gl_skyclip.value;
4809 r_refdef.fog_height = 1<<30;
4810 r_refdef.fog_fadedepth = 128;
4812 else if (r_refdef.oldgl_fogenable)
4814 r_refdef.oldgl_fogenable = false;
4815 r_refdef.fog_density = 0;
4816 r_refdef.fog_red = 0;
4817 r_refdef.fog_green = 0;
4818 r_refdef.fog_blue = 0;
4819 r_refdef.fog_alpha = 0;
4820 r_refdef.fog_start = 0;
4821 r_refdef.fog_end = 0;
4822 r_refdef.fog_height = 1<<30;
4823 r_refdef.fog_fadedepth = 128;
4827 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4828 r_refdef.fog_start = max(0, r_refdef.fog_start);
4829 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4831 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4833 if (r_refdef.fog_density && r_drawfog.integer)
4835 r_refdef.fogenabled = true;
4836 // this is the point where the fog reaches 0.9986 alpha, which we
4837 // consider a good enough cutoff point for the texture
4838 // (0.9986 * 256 == 255.6)
4839 if (r_fog_exp2.integer)
4840 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4842 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4843 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4844 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4845 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4846 // fog color was already set
4847 // update the fog texture
4848 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)
4849 R_BuildFogTexture();
4852 r_refdef.fogenabled = false;
4854 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4856 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4858 // build GLSL gamma texture
4859 #define RAMPWIDTH 256
4860 unsigned short ramp[RAMPWIDTH * 3];
4861 unsigned char rampbgr[RAMPWIDTH][4];
4864 r_texture_gammaramps_serial = vid_gammatables_serial;
4866 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4867 for(i = 0; i < RAMPWIDTH; ++i)
4869 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4870 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4871 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4874 if (r_texture_gammaramps)
4876 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4880 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);
4886 // remove GLSL gamma texture
4890 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4891 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4897 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4898 if( scenetype != r_currentscenetype ) {
4899 // store the old scenetype
4900 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4901 r_currentscenetype = scenetype;
4902 // move in the new scene
4903 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4912 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4914 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4915 if( scenetype == r_currentscenetype ) {
4916 return &r_refdef.scene;
4918 return &r_scenes_store[ scenetype ];
4927 void R_RenderView(void)
4929 if (r_timereport_active)
4930 R_TimeReport("start");
4931 r_frame++; // used only by R_GetCurrentTexture
4932 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4934 R_AnimCache_NewFrame();
4936 if (r_refdef.view.isoverlay)
4938 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4939 GL_Clear( GL_DEPTH_BUFFER_BIT );
4940 R_TimeReport("depthclear");
4942 r_refdef.view.showdebug = false;
4944 r_waterstate.enabled = false;
4945 r_waterstate.numwaterplanes = 0;
4953 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4954 return; //Host_Error ("R_RenderView: NULL worldmodel");
4956 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4958 // break apart the view matrix into vectors for various purposes
4959 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4960 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4961 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4962 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4963 // make an inverted copy of the view matrix for tracking sprites
4964 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4966 R_Shadow_UpdateWorldLightSelection();
4968 R_Bloom_StartFrame();
4969 R_Water_StartFrame();
4972 if (r_timereport_active)
4973 R_TimeReport("viewsetup");
4975 R_ResetViewRendering3D();
4977 if (r_refdef.view.clear || r_refdef.fogenabled)
4979 R_ClearScreen(r_refdef.fogenabled);
4980 if (r_timereport_active)
4981 R_TimeReport("viewclear");
4983 r_refdef.view.clear = true;
4985 // this produces a bloom texture to be used in R_BlendView() later
4986 if (r_hdr.integer && r_bloomstate.bloomwidth)
4987 R_HDR_RenderBloomTexture();
4989 r_refdef.view.showdebug = true;
4992 if (r_timereport_active)
4993 R_TimeReport("visibility");
4995 r_waterstate.numwaterplanes = 0;
4996 if (r_waterstate.enabled)
4997 R_RenderWaterPlanes();
5000 r_waterstate.numwaterplanes = 0;
5003 if (r_timereport_active)
5004 R_TimeReport("blendview");
5006 GL_Scissor(0, 0, vid.width, vid.height);
5007 GL_ScissorTest(false);
5011 void R_RenderWaterPlanes(void)
5013 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5015 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5016 if (r_timereport_active)
5017 R_TimeReport("waterworld");
5020 // don't let sound skip if going slow
5021 if (r_refdef.scene.extraupdate)
5024 R_DrawModelsAddWaterPlanes();
5025 if (r_timereport_active)
5026 R_TimeReport("watermodels");
5028 if (r_waterstate.numwaterplanes)
5030 R_Water_ProcessPlanes();
5031 if (r_timereport_active)
5032 R_TimeReport("waterscenes");
5036 extern void R_DrawLightningBeams (void);
5037 extern void VM_CL_AddPolygonsToMeshQueue (void);
5038 extern void R_DrawPortals (void);
5039 extern cvar_t cl_locs_show;
5040 static void R_DrawLocs(void);
5041 static void R_DrawEntityBBoxes(void);
5042 static void R_DrawModelDecals(void);
5043 extern cvar_t cl_decals_newsystem;
5044 void R_RenderScene(void)
5046 r_refdef.stats.renders++;
5050 // don't let sound skip if going slow
5051 if (r_refdef.scene.extraupdate)
5054 R_MeshQueue_BeginScene();
5058 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);
5060 if (cl.csqc_vidvars.drawworld)
5062 // don't let sound skip if going slow
5063 if (r_refdef.scene.extraupdate)
5066 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5068 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5069 if (r_timereport_active)
5070 R_TimeReport("worldsky");
5073 if (R_DrawBrushModelsSky() && r_timereport_active)
5074 R_TimeReport("bmodelsky");
5076 if (skyrendermasked && skyrenderlater)
5078 // we have to force off the water clipping plane while rendering sky
5085 R_AnimCache_CacheVisibleEntities();
5087 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5089 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5090 if (r_timereport_active)
5091 R_TimeReport("worlddepth");
5093 if (r_depthfirst.integer >= 2)
5095 R_DrawModelsDepth();
5096 if (r_timereport_active)
5097 R_TimeReport("modeldepth");
5100 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5102 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5103 if (r_timereport_active)
5104 R_TimeReport("world");
5107 // don't let sound skip if going slow
5108 if (r_refdef.scene.extraupdate)
5112 if (r_timereport_active)
5113 R_TimeReport("models");
5115 // don't let sound skip if going slow
5116 if (r_refdef.scene.extraupdate)
5119 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5121 R_DrawModelShadows();
5122 R_ResetViewRendering3D();
5123 // don't let sound skip if going slow
5124 if (r_refdef.scene.extraupdate)
5128 R_ShadowVolumeLighting(false);
5129 if (r_timereport_active)
5130 R_TimeReport("rtlights");
5132 // don't let sound skip if going slow
5133 if (r_refdef.scene.extraupdate)
5136 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5138 R_DrawModelShadows();
5139 R_ResetViewRendering3D();
5140 // don't let sound skip if going slow
5141 if (r_refdef.scene.extraupdate)
5145 if (cl.csqc_vidvars.drawworld)
5147 if (cl_decals_newsystem.integer)
5149 R_DrawModelDecals();
5150 if (r_timereport_active)
5151 R_TimeReport("modeldecals");
5156 if (r_timereport_active)
5157 R_TimeReport("decals");
5161 if (r_timereport_active)
5162 R_TimeReport("particles");
5165 if (r_timereport_active)
5166 R_TimeReport("explosions");
5168 R_DrawLightningBeams();
5169 if (r_timereport_active)
5170 R_TimeReport("lightning");
5173 R_SetupGenericShader(true);
5174 VM_CL_AddPolygonsToMeshQueue();
5176 if (r_refdef.view.showdebug)
5178 if (cl_locs_show.integer)
5181 if (r_timereport_active)
5182 R_TimeReport("showlocs");
5185 if (r_drawportals.integer)
5188 if (r_timereport_active)
5189 R_TimeReport("portals");
5192 if (r_showbboxes.value > 0)
5194 R_DrawEntityBBoxes();
5195 if (r_timereport_active)
5196 R_TimeReport("bboxes");
5200 R_SetupGenericShader(true);
5201 R_MeshQueue_RenderTransparent();
5202 if (r_timereport_active)
5203 R_TimeReport("drawtrans");
5205 R_SetupGenericShader(true);
5207 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))
5209 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5210 if (r_timereport_active)
5211 R_TimeReport("worlddebug");
5212 R_DrawModelsDebug();
5213 if (r_timereport_active)
5214 R_TimeReport("modeldebug");
5217 R_SetupGenericShader(true);
5219 if (cl.csqc_vidvars.drawworld)
5222 if (r_timereport_active)
5223 R_TimeReport("coronas");
5226 // don't let sound skip if going slow
5227 if (r_refdef.scene.extraupdate)
5230 R_ResetViewRendering2D();
5233 static const unsigned short bboxelements[36] =
5243 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5246 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5248 RSurf_ActiveWorldEntity();
5250 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5251 GL_DepthMask(false);
5252 GL_DepthRange(0, 1);
5253 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5254 R_Mesh_ResetTextureState();
5256 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5257 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5258 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5259 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5260 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5261 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5262 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5263 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5264 R_FillColors(color4f, 8, cr, cg, cb, ca);
5265 if (r_refdef.fogenabled)
5267 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5269 f1 = RSurf_FogVertex(v);
5271 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5272 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5273 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5276 R_Mesh_VertexPointer(vertex3f, 0, 0);
5277 R_Mesh_ColorPointer(color4f, 0, 0);
5278 R_Mesh_ResetTextureState();
5279 R_SetupGenericShader(false);
5280 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5283 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5287 prvm_edict_t *edict;
5288 prvm_prog_t *prog_save = prog;
5290 // this function draws bounding boxes of server entities
5294 GL_CullFace(GL_NONE);
5295 R_SetupGenericShader(false);
5299 for (i = 0;i < numsurfaces;i++)
5301 edict = PRVM_EDICT_NUM(surfacelist[i]);
5302 switch ((int)edict->fields.server->solid)
5304 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5305 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5306 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5307 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5308 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5309 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5311 color[3] *= r_showbboxes.value;
5312 color[3] = bound(0, color[3], 1);
5313 GL_DepthTest(!r_showdisabledepthtest.integer);
5314 GL_CullFace(r_refdef.view.cullface_front);
5315 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5321 static void R_DrawEntityBBoxes(void)
5324 prvm_edict_t *edict;
5326 prvm_prog_t *prog_save = prog;
5328 // this function draws bounding boxes of server entities
5334 for (i = 0;i < prog->num_edicts;i++)
5336 edict = PRVM_EDICT_NUM(i);
5337 if (edict->priv.server->free)
5339 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5340 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5342 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5344 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5345 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5351 static const int nomodelelement3i[24] =
5363 static const unsigned short nomodelelement3s[24] =
5375 static const float nomodelvertex3f[6*3] =
5385 static const float nomodelcolor4f[6*4] =
5387 0.0f, 0.0f, 0.5f, 1.0f,
5388 0.0f, 0.0f, 0.5f, 1.0f,
5389 0.0f, 0.5f, 0.0f, 1.0f,
5390 0.0f, 0.5f, 0.0f, 1.0f,
5391 0.5f, 0.0f, 0.0f, 1.0f,
5392 0.5f, 0.0f, 0.0f, 1.0f
5395 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5401 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);
5403 // this is only called once per entity so numsurfaces is always 1, and
5404 // surfacelist is always {0}, so this code does not handle batches
5406 if (rsurface.ent_flags & RENDER_ADDITIVE)
5408 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5409 GL_DepthMask(false);
5411 else if (rsurface.ent_color[3] < 1)
5413 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5414 GL_DepthMask(false);
5418 GL_BlendFunc(GL_ONE, GL_ZERO);
5421 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5422 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5423 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5424 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5425 R_SetupGenericShader(false);
5426 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5427 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5428 R_Mesh_ColorPointer(color4f, 0, 0);
5429 for (i = 0, c = color4f;i < 6;i++, c += 4)
5431 c[0] *= rsurface.ent_color[0];
5432 c[1] *= rsurface.ent_color[1];
5433 c[2] *= rsurface.ent_color[2];
5434 c[3] *= rsurface.ent_color[3];
5436 if (r_refdef.fogenabled)
5438 for (i = 0, c = color4f;i < 6;i++, c += 4)
5440 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5442 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5443 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5444 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5447 R_Mesh_ResetTextureState();
5448 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5451 void R_DrawNoModel(entity_render_t *ent)
5454 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5455 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5456 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5458 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5461 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5463 vec3_t right1, right2, diff, normal;
5465 VectorSubtract (org2, org1, normal);
5467 // calculate 'right' vector for start
5468 VectorSubtract (r_refdef.view.origin, org1, diff);
5469 CrossProduct (normal, diff, right1);
5470 VectorNormalize (right1);
5472 // calculate 'right' vector for end
5473 VectorSubtract (r_refdef.view.origin, org2, diff);
5474 CrossProduct (normal, diff, right2);
5475 VectorNormalize (right2);
5477 vert[ 0] = org1[0] + width * right1[0];
5478 vert[ 1] = org1[1] + width * right1[1];
5479 vert[ 2] = org1[2] + width * right1[2];
5480 vert[ 3] = org1[0] - width * right1[0];
5481 vert[ 4] = org1[1] - width * right1[1];
5482 vert[ 5] = org1[2] - width * right1[2];
5483 vert[ 6] = org2[0] - width * right2[0];
5484 vert[ 7] = org2[1] - width * right2[1];
5485 vert[ 8] = org2[2] - width * right2[2];
5486 vert[ 9] = org2[0] + width * right2[0];
5487 vert[10] = org2[1] + width * right2[1];
5488 vert[11] = org2[2] + width * right2[2];
5491 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)
5493 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5494 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5495 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5496 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5497 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5498 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5499 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5500 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5501 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5502 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5503 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5504 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5507 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5512 VectorSet(v, x, y, z);
5513 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5514 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5516 if (i == mesh->numvertices)
5518 if (mesh->numvertices < mesh->maxvertices)
5520 VectorCopy(v, vertex3f);
5521 mesh->numvertices++;
5523 return mesh->numvertices;
5529 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5533 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5534 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5535 e = mesh->element3i + mesh->numtriangles * 3;
5536 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5538 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5539 if (mesh->numtriangles < mesh->maxtriangles)
5544 mesh->numtriangles++;
5546 element[1] = element[2];
5550 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5554 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5555 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5556 e = mesh->element3i + mesh->numtriangles * 3;
5557 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5559 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5560 if (mesh->numtriangles < mesh->maxtriangles)
5565 mesh->numtriangles++;
5567 element[1] = element[2];
5571 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5572 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5574 int planenum, planenum2;
5577 mplane_t *plane, *plane2;
5579 double temppoints[2][256*3];
5580 // figure out how large a bounding box we need to properly compute this brush
5582 for (w = 0;w < numplanes;w++)
5583 maxdist = max(maxdist, fabs(planes[w].dist));
5584 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5585 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5586 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5590 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5591 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5593 if (planenum2 == planenum)
5595 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);
5598 if (tempnumpoints < 3)
5600 // generate elements forming a triangle fan for this polygon
5601 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5605 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)
5607 texturelayer_t *layer;
5608 layer = t->currentlayers + t->currentnumlayers++;
5610 layer->depthmask = depthmask;
5611 layer->blendfunc1 = blendfunc1;
5612 layer->blendfunc2 = blendfunc2;
5613 layer->texture = texture;
5614 layer->texmatrix = *matrix;
5615 layer->color[0] = r * r_refdef.view.colorscale;
5616 layer->color[1] = g * r_refdef.view.colorscale;
5617 layer->color[2] = b * r_refdef.view.colorscale;
5618 layer->color[3] = a;
5621 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5624 index = parms[2] + r_refdef.scene.time * parms[3];
5625 index -= floor(index);
5629 case Q3WAVEFUNC_NONE:
5630 case Q3WAVEFUNC_NOISE:
5631 case Q3WAVEFUNC_COUNT:
5634 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5635 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5636 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5637 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5638 case Q3WAVEFUNC_TRIANGLE:
5640 f = index - floor(index);
5651 return (float)(parms[0] + parms[1] * f);
5654 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5659 matrix4x4_t matrix, temp;
5660 switch(tcmod->tcmod)
5664 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5665 matrix = r_waterscrollmatrix;
5667 matrix = identitymatrix;
5669 case Q3TCMOD_ENTITYTRANSLATE:
5670 // this is used in Q3 to allow the gamecode to control texcoord
5671 // scrolling on the entity, which is not supported in darkplaces yet.
5672 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5674 case Q3TCMOD_ROTATE:
5675 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5676 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5677 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5680 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5682 case Q3TCMOD_SCROLL:
5683 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5685 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5686 w = (int) tcmod->parms[0];
5687 h = (int) tcmod->parms[1];
5688 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5690 idx = (int) floor(f * w * h);
5691 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5693 case Q3TCMOD_STRETCH:
5694 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5695 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5697 case Q3TCMOD_TRANSFORM:
5698 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5699 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5700 VectorSet(tcmat + 6, 0 , 0 , 1);
5701 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5702 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5704 case Q3TCMOD_TURBULENT:
5705 // this is handled in the RSurf_PrepareVertices function
5706 matrix = identitymatrix;
5710 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5713 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5715 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5716 char name[MAX_QPATH];
5717 skinframe_t *skinframe;
5718 unsigned char pixels[296*194];
5719 strlcpy(cache->name, skinname, sizeof(cache->name));
5720 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5721 if (developer_loading.integer)
5722 Con_Printf("loading %s\n", name);
5723 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5724 if (!skinframe || !skinframe->base)
5727 fs_offset_t filesize;
5729 f = FS_LoadFile(name, tempmempool, true, &filesize);
5732 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5733 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5737 cache->skinframe = skinframe;
5740 texture_t *R_GetCurrentTexture(texture_t *t)
5743 const entity_render_t *ent = rsurface.entity;
5744 dp_model_t *model = ent->model;
5745 q3shaderinfo_layer_tcmod_t *tcmod;
5747 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5748 return t->currentframe;
5749 t->update_lastrenderframe = r_frame;
5750 t->update_lastrenderentity = (void *)ent;
5752 // switch to an alternate material if this is a q1bsp animated material
5754 texture_t *texture = t;
5755 int s = rsurface.ent_skinnum;
5756 if ((unsigned int)s >= (unsigned int)model->numskins)
5758 if (model->skinscenes)
5760 if (model->skinscenes[s].framecount > 1)
5761 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5763 s = model->skinscenes[s].firstframe;
5766 t = t + s * model->num_surfaces;
5769 // use an alternate animation if the entity's frame is not 0,
5770 // and only if the texture has an alternate animation
5771 if (rsurface.ent_alttextures && t->anim_total[1])
5772 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5774 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5776 texture->currentframe = t;
5779 // update currentskinframe to be a qw skin or animation frame
5780 if (rsurface.ent_qwskin >= 0)
5782 i = rsurface.ent_qwskin;
5783 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5785 r_qwskincache_size = cl.maxclients;
5787 Mem_Free(r_qwskincache);
5788 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5790 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5791 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5792 t->currentskinframe = r_qwskincache[i].skinframe;
5793 if (t->currentskinframe == NULL)
5794 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5796 else if (t->numskinframes >= 2)
5797 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5798 if (t->backgroundnumskinframes >= 2)
5799 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5801 t->currentmaterialflags = t->basematerialflags;
5802 t->currentalpha = rsurface.ent_color[3];
5803 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5804 t->currentalpha *= r_wateralpha.value;
5805 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5806 t->currentalpha *= t->r_water_wateralpha;
5807 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5808 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5809 if (!(rsurface.ent_flags & RENDER_LIGHT))
5810 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5811 else if (rsurface.modeltexcoordlightmap2f == NULL)
5813 // pick a model lighting mode
5814 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5815 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5817 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5819 if (rsurface.ent_flags & RENDER_ADDITIVE)
5820 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5821 else if (t->currentalpha < 1)
5822 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5823 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5824 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5825 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5826 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5827 if (t->backgroundnumskinframes)
5828 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5829 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5831 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5832 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5835 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5837 // there is no tcmod
5838 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5840 t->currenttexmatrix = r_waterscrollmatrix;
5841 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5843 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
5845 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5846 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5849 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5850 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5851 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5852 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5854 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5855 if (t->currentskinframe->qpixels)
5856 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
5857 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5858 t->glosstexture = r_texture_black;
5859 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5860 t->backgroundglosstexture = r_texture_black;
5861 t->specularpower = r_shadow_glossexponent.value;
5862 // TODO: store reference values for these in the texture?
5863 t->specularscale = 0;
5864 if (r_shadow_gloss.integer > 0)
5866 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5868 if (r_shadow_glossintensity.value > 0)
5870 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5871 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5872 t->specularscale = r_shadow_glossintensity.value;
5875 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5877 t->glosstexture = r_texture_white;
5878 t->backgroundglosstexture = r_texture_white;
5879 t->specularscale = r_shadow_gloss2intensity.value;
5880 t->specularpower = r_shadow_gloss2exponent.value;
5883 t->specularscale *= t->specularscalemod;
5884 t->specularpower *= t->specularpowermod;
5886 // lightmaps mode looks bad with dlights using actual texturing, so turn
5887 // off the colormap and glossmap, but leave the normalmap on as it still
5888 // accurately represents the shading involved
5889 if (gl_lightmaps.integer)
5891 t->basetexture = r_texture_grey128;
5892 t->backgroundbasetexture = NULL;
5893 t->specularscale = 0;
5894 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5897 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5898 VectorClear(t->dlightcolor);
5899 t->currentnumlayers = 0;
5900 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5903 int blendfunc1, blendfunc2;
5905 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5907 blendfunc1 = GL_SRC_ALPHA;
5908 blendfunc2 = GL_ONE;
5910 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5912 blendfunc1 = GL_SRC_ALPHA;
5913 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5915 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5917 blendfunc1 = t->customblendfunc[0];
5918 blendfunc2 = t->customblendfunc[1];
5922 blendfunc1 = GL_ONE;
5923 blendfunc2 = GL_ZERO;
5925 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5926 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5927 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5928 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5930 // fullbright is not affected by r_refdef.lightmapintensity
5931 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]);
5932 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5933 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]);
5934 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5935 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]);
5939 vec3_t ambientcolor;
5941 // set the color tint used for lights affecting this surface
5942 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5944 // q3bsp has no lightmap updates, so the lightstylevalue that
5945 // would normally be baked into the lightmap must be
5946 // applied to the color
5947 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5948 if (model->type == mod_brushq3)
5949 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5950 colorscale *= r_refdef.lightmapintensity;
5951 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5952 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5953 // basic lit geometry
5954 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]);
5955 // add pants/shirt if needed
5956 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5957 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]);
5958 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5959 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]);
5960 // now add ambient passes if needed
5961 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5963 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]);
5964 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5965 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]);
5966 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5967 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]);
5970 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5971 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]);
5972 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5974 // if this is opaque use alpha blend which will darken the earlier
5977 // if this is an alpha blended material, all the earlier passes
5978 // were darkened by fog already, so we only need to add the fog
5979 // color ontop through the fog mask texture
5981 // if this is an additive blended material, all the earlier passes
5982 // were darkened by fog already, and we should not add fog color
5983 // (because the background was not darkened, there is no fog color
5984 // that was lost behind it).
5985 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]);
5989 return t->currentframe;
5992 rsurfacestate_t rsurface;
5994 void R_Mesh_ResizeArrays(int newvertices)
5997 if (rsurface.array_size >= newvertices)
5999 if (rsurface.array_modelvertex3f)
6000 Mem_Free(rsurface.array_modelvertex3f);
6001 rsurface.array_size = (newvertices + 1023) & ~1023;
6002 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
6003 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
6004 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
6005 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
6006 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
6007 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
6008 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
6009 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
6010 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
6011 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
6012 rsurface.array_color4f = base + rsurface.array_size * 27;
6013 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6016 void RSurf_ActiveWorldEntity(void)
6018 dp_model_t *model = r_refdef.scene.worldmodel;
6019 //if (rsurface.entity == r_refdef.scene.worldentity)
6021 rsurface.entity = r_refdef.scene.worldentity;
6022 rsurface.skeleton = NULL;
6023 rsurface.ent_skinnum = 0;
6024 rsurface.ent_qwskin = -1;
6025 rsurface.ent_shadertime = 0;
6026 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
6027 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6028 if (rsurface.array_size < model->surfmesh.num_vertices)
6029 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6030 rsurface.matrix = identitymatrix;
6031 rsurface.inversematrix = identitymatrix;
6032 rsurface.matrixscale = 1;
6033 rsurface.inversematrixscale = 1;
6034 R_Mesh_Matrix(&identitymatrix);
6035 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6036 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6037 rsurface.fograngerecip = r_refdef.fograngerecip;
6038 rsurface.fogheightfade = r_refdef.fogheightfade;
6039 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6040 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6041 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6042 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6043 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6044 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6045 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6046 VectorSet(rsurface.glowmod, 1, 1, 1);
6047 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6048 rsurface.frameblend[0].lerp = 1;
6049 rsurface.ent_alttextures = false;
6050 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6051 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6052 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6053 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6054 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6055 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6056 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6057 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6058 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6059 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6060 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6061 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6062 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6063 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6064 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6065 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6066 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6067 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6068 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6069 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6070 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6071 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6072 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6073 rsurface.modelelement3i = model->surfmesh.data_element3i;
6074 rsurface.modelelement3s = model->surfmesh.data_element3s;
6075 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6076 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6077 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6078 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6079 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6080 rsurface.modelsurfaces = model->data_surfaces;
6081 rsurface.generatedvertex = false;
6082 rsurface.vertex3f = rsurface.modelvertex3f;
6083 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6084 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6085 rsurface.svector3f = rsurface.modelsvector3f;
6086 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6087 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6088 rsurface.tvector3f = rsurface.modeltvector3f;
6089 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6090 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6091 rsurface.normal3f = rsurface.modelnormal3f;
6092 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6093 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6094 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6097 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6099 dp_model_t *model = ent->model;
6100 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6102 rsurface.entity = (entity_render_t *)ent;
6103 rsurface.skeleton = ent->skeleton;
6104 rsurface.ent_skinnum = ent->skinnum;
6105 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;
6106 rsurface.ent_shadertime = ent->shadertime;
6107 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6108 rsurface.ent_flags = ent->flags;
6109 if (rsurface.array_size < model->surfmesh.num_vertices)
6110 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6111 rsurface.matrix = ent->matrix;
6112 rsurface.inversematrix = ent->inversematrix;
6113 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6114 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6115 R_Mesh_Matrix(&rsurface.matrix);
6116 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6117 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6118 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6119 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6120 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6121 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6122 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6123 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6124 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6125 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6126 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6127 VectorCopy(ent->glowmod, rsurface.glowmod);
6128 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6129 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6130 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6131 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6132 if (ent->model->brush.submodel)
6134 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6135 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6137 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6139 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6141 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6142 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6143 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6144 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6146 else if (wanttangents)
6148 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6149 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6150 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6151 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6152 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6154 else if (wantnormals)
6156 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6157 rsurface.modelsvector3f = NULL;
6158 rsurface.modeltvector3f = NULL;
6159 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6160 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6164 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6165 rsurface.modelsvector3f = NULL;
6166 rsurface.modeltvector3f = NULL;
6167 rsurface.modelnormal3f = NULL;
6168 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6170 rsurface.modelvertex3f_bufferobject = 0;
6171 rsurface.modelvertex3f_bufferoffset = 0;
6172 rsurface.modelsvector3f_bufferobject = 0;
6173 rsurface.modelsvector3f_bufferoffset = 0;
6174 rsurface.modeltvector3f_bufferobject = 0;
6175 rsurface.modeltvector3f_bufferoffset = 0;
6176 rsurface.modelnormal3f_bufferobject = 0;
6177 rsurface.modelnormal3f_bufferoffset = 0;
6178 rsurface.generatedvertex = true;
6182 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6183 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6184 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6185 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6186 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6187 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6188 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6189 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6190 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6191 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6192 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6193 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6194 rsurface.generatedvertex = false;
6196 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6197 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6198 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6199 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6200 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6201 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6202 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6203 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6204 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6205 rsurface.modelelement3i = model->surfmesh.data_element3i;
6206 rsurface.modelelement3s = model->surfmesh.data_element3s;
6207 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6208 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6209 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6210 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6211 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6212 rsurface.modelsurfaces = model->data_surfaces;
6213 rsurface.vertex3f = rsurface.modelvertex3f;
6214 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6215 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6216 rsurface.svector3f = rsurface.modelsvector3f;
6217 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6218 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6219 rsurface.tvector3f = rsurface.modeltvector3f;
6220 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6221 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6222 rsurface.normal3f = rsurface.modelnormal3f;
6223 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6224 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6225 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6228 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)
6230 rsurface.entity = r_refdef.scene.worldentity;
6231 rsurface.skeleton = NULL;
6232 rsurface.ent_skinnum = 0;
6233 rsurface.ent_qwskin = -1;
6234 rsurface.ent_shadertime = shadertime;
6235 Vector4Set(rsurface.ent_color, r, g, b, a);
6236 rsurface.ent_flags = entflags;
6237 rsurface.modelnum_vertices = numvertices;
6238 rsurface.modelnum_triangles = numtriangles;
6239 if (rsurface.array_size < rsurface.modelnum_vertices)
6240 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6241 rsurface.matrix = *matrix;
6242 rsurface.inversematrix = *inversematrix;
6243 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6244 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6245 R_Mesh_Matrix(&rsurface.matrix);
6246 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6247 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6248 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6249 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6250 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6251 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6252 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6253 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6254 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6255 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6256 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6257 VectorSet(rsurface.glowmod, 1, 1, 1);
6258 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6259 rsurface.frameblend[0].lerp = 1;
6260 rsurface.ent_alttextures = false;
6261 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6262 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6265 rsurface.modelvertex3f = vertex3f;
6266 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6267 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6268 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6270 else if (wantnormals)
6272 rsurface.modelvertex3f = vertex3f;
6273 rsurface.modelsvector3f = NULL;
6274 rsurface.modeltvector3f = NULL;
6275 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6279 rsurface.modelvertex3f = vertex3f;
6280 rsurface.modelsvector3f = NULL;
6281 rsurface.modeltvector3f = NULL;
6282 rsurface.modelnormal3f = NULL;
6284 rsurface.modelvertex3f_bufferobject = 0;
6285 rsurface.modelvertex3f_bufferoffset = 0;
6286 rsurface.modelsvector3f_bufferobject = 0;
6287 rsurface.modelsvector3f_bufferoffset = 0;
6288 rsurface.modeltvector3f_bufferobject = 0;
6289 rsurface.modeltvector3f_bufferoffset = 0;
6290 rsurface.modelnormal3f_bufferobject = 0;
6291 rsurface.modelnormal3f_bufferoffset = 0;
6292 rsurface.generatedvertex = true;
6293 rsurface.modellightmapcolor4f = color4f;
6294 rsurface.modellightmapcolor4f_bufferobject = 0;
6295 rsurface.modellightmapcolor4f_bufferoffset = 0;
6296 rsurface.modeltexcoordtexture2f = texcoord2f;
6297 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6298 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6299 rsurface.modeltexcoordlightmap2f = NULL;
6300 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6301 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6302 rsurface.modelelement3i = element3i;
6303 rsurface.modelelement3s = element3s;
6304 rsurface.modelelement3i_bufferobject = 0;
6305 rsurface.modelelement3s_bufferobject = 0;
6306 rsurface.modellightmapoffsets = NULL;
6307 rsurface.modelsurfaces = NULL;
6308 rsurface.vertex3f = rsurface.modelvertex3f;
6309 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6310 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6311 rsurface.svector3f = rsurface.modelsvector3f;
6312 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6313 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6314 rsurface.tvector3f = rsurface.modeltvector3f;
6315 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6316 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6317 rsurface.normal3f = rsurface.modelnormal3f;
6318 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6319 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6320 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6322 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6324 if ((wantnormals || wanttangents) && !normal3f)
6325 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6326 if (wanttangents && !svector3f)
6327 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);
6331 float RSurf_FogPoint(const float *v)
6333 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6334 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6335 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6336 float FogHeightFade = r_refdef.fogheightfade;
6338 unsigned int fogmasktableindex;
6339 if (r_refdef.fogplaneviewabove)
6340 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6342 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6343 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6344 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6347 float RSurf_FogVertex(const float *v)
6349 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6350 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6351 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6352 float FogHeightFade = rsurface.fogheightfade;
6354 unsigned int fogmasktableindex;
6355 if (r_refdef.fogplaneviewabove)
6356 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6358 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6359 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6360 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6363 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6364 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6367 int texturesurfaceindex;
6372 const float *v1, *in_tc;
6374 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6376 q3shaderinfo_deform_t *deform;
6377 // 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
6378 if (rsurface.generatedvertex)
6380 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6381 generatenormals = true;
6382 for (i = 0;i < Q3MAXDEFORMS;i++)
6384 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6386 generatetangents = true;
6387 generatenormals = true;
6389 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6390 generatenormals = true;
6392 if (generatenormals && !rsurface.modelnormal3f)
6394 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6395 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6396 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6397 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6399 if (generatetangents && !rsurface.modelsvector3f)
6401 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6402 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6403 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6404 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6405 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6406 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6407 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);
6410 rsurface.vertex3f = rsurface.modelvertex3f;
6411 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6412 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6413 rsurface.svector3f = rsurface.modelsvector3f;
6414 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6415 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6416 rsurface.tvector3f = rsurface.modeltvector3f;
6417 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6418 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6419 rsurface.normal3f = rsurface.modelnormal3f;
6420 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6421 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6422 // if vertices are deformed (sprite flares and things in maps, possibly
6423 // water waves, bulges and other deformations), generate them into
6424 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6425 // (may be static model data or generated data for an animated model, or
6426 // the previous deform pass)
6427 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6429 switch (deform->deform)
6432 case Q3DEFORM_PROJECTIONSHADOW:
6433 case Q3DEFORM_TEXT0:
6434 case Q3DEFORM_TEXT1:
6435 case Q3DEFORM_TEXT2:
6436 case Q3DEFORM_TEXT3:
6437 case Q3DEFORM_TEXT4:
6438 case Q3DEFORM_TEXT5:
6439 case Q3DEFORM_TEXT6:
6440 case Q3DEFORM_TEXT7:
6443 case Q3DEFORM_AUTOSPRITE:
6444 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6445 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6446 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6447 VectorNormalize(newforward);
6448 VectorNormalize(newright);
6449 VectorNormalize(newup);
6450 // make deformed versions of only the model vertices used by the specified surfaces
6451 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6453 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6454 // a single autosprite surface can contain multiple sprites...
6455 for (j = 0;j < surface->num_vertices - 3;j += 4)
6457 VectorClear(center);
6458 for (i = 0;i < 4;i++)
6459 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6460 VectorScale(center, 0.25f, center);
6461 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6462 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6463 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6464 for (i = 0;i < 4;i++)
6466 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6467 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6470 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);
6471 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);
6473 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6474 rsurface.vertex3f_bufferobject = 0;
6475 rsurface.vertex3f_bufferoffset = 0;
6476 rsurface.svector3f = rsurface.array_deformedsvector3f;
6477 rsurface.svector3f_bufferobject = 0;
6478 rsurface.svector3f_bufferoffset = 0;
6479 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6480 rsurface.tvector3f_bufferobject = 0;
6481 rsurface.tvector3f_bufferoffset = 0;
6482 rsurface.normal3f = rsurface.array_deformednormal3f;
6483 rsurface.normal3f_bufferobject = 0;
6484 rsurface.normal3f_bufferoffset = 0;
6486 case Q3DEFORM_AUTOSPRITE2:
6487 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6488 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6489 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6490 VectorNormalize(newforward);
6491 VectorNormalize(newright);
6492 VectorNormalize(newup);
6493 // make deformed versions of only the model vertices used by the specified surfaces
6494 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6496 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6497 const float *v1, *v2;
6507 memset(shortest, 0, sizeof(shortest));
6508 // a single autosprite surface can contain multiple sprites...
6509 for (j = 0;j < surface->num_vertices - 3;j += 4)
6511 VectorClear(center);
6512 for (i = 0;i < 4;i++)
6513 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6514 VectorScale(center, 0.25f, center);
6515 // find the two shortest edges, then use them to define the
6516 // axis vectors for rotating around the central axis
6517 for (i = 0;i < 6;i++)
6519 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6520 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6522 Debug_PolygonBegin(NULL, 0);
6523 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6524 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);
6525 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6528 l = VectorDistance2(v1, v2);
6529 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6531 l += (1.0f / 1024.0f);
6532 if (shortest[0].length2 > l || i == 0)
6534 shortest[1] = shortest[0];
6535 shortest[0].length2 = l;
6536 shortest[0].v1 = v1;
6537 shortest[0].v2 = v2;
6539 else if (shortest[1].length2 > l || i == 1)
6541 shortest[1].length2 = l;
6542 shortest[1].v1 = v1;
6543 shortest[1].v2 = v2;
6546 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6547 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6549 Debug_PolygonBegin(NULL, 0);
6550 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6551 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);
6552 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6555 // this calculates the right vector from the shortest edge
6556 // and the up vector from the edge midpoints
6557 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6558 VectorNormalize(right);
6559 VectorSubtract(end, start, up);
6560 VectorNormalize(up);
6561 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6562 VectorSubtract(rsurface.localvieworigin, center, forward);
6563 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6564 VectorNegate(forward, forward);
6565 VectorReflect(forward, 0, up, forward);
6566 VectorNormalize(forward);
6567 CrossProduct(up, forward, newright);
6568 VectorNormalize(newright);
6570 Debug_PolygonBegin(NULL, 0);
6571 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);
6572 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6573 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6577 Debug_PolygonBegin(NULL, 0);
6578 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6579 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6580 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6583 // rotate the quad around the up axis vector, this is made
6584 // especially easy by the fact we know the quad is flat,
6585 // so we only have to subtract the center position and
6586 // measure distance along the right vector, and then
6587 // multiply that by the newright vector and add back the
6589 // we also need to subtract the old position to undo the
6590 // displacement from the center, which we do with a
6591 // DotProduct, the subtraction/addition of center is also
6592 // optimized into DotProducts here
6593 l = DotProduct(right, center);
6594 for (i = 0;i < 4;i++)
6596 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6597 f = DotProduct(right, v1) - l;
6598 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6601 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);
6602 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);
6604 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6605 rsurface.vertex3f_bufferobject = 0;
6606 rsurface.vertex3f_bufferoffset = 0;
6607 rsurface.svector3f = rsurface.array_deformedsvector3f;
6608 rsurface.svector3f_bufferobject = 0;
6609 rsurface.svector3f_bufferoffset = 0;
6610 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6611 rsurface.tvector3f_bufferobject = 0;
6612 rsurface.tvector3f_bufferoffset = 0;
6613 rsurface.normal3f = rsurface.array_deformednormal3f;
6614 rsurface.normal3f_bufferobject = 0;
6615 rsurface.normal3f_bufferoffset = 0;
6617 case Q3DEFORM_NORMAL:
6618 // deform the normals to make reflections wavey
6619 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6621 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6622 for (j = 0;j < surface->num_vertices;j++)
6625 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6626 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6627 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6628 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6629 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6630 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6631 VectorNormalize(normal);
6633 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);
6635 rsurface.svector3f = rsurface.array_deformedsvector3f;
6636 rsurface.svector3f_bufferobject = 0;
6637 rsurface.svector3f_bufferoffset = 0;
6638 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6639 rsurface.tvector3f_bufferobject = 0;
6640 rsurface.tvector3f_bufferoffset = 0;
6641 rsurface.normal3f = rsurface.array_deformednormal3f;
6642 rsurface.normal3f_bufferobject = 0;
6643 rsurface.normal3f_bufferoffset = 0;
6646 // deform vertex array to make wavey water and flags and such
6647 waveparms[0] = deform->waveparms[0];
6648 waveparms[1] = deform->waveparms[1];
6649 waveparms[2] = deform->waveparms[2];
6650 waveparms[3] = deform->waveparms[3];
6651 // this is how a divisor of vertex influence on deformation
6652 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6653 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6654 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6656 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6657 for (j = 0;j < surface->num_vertices;j++)
6659 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6660 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6661 // if the wavefunc depends on time, evaluate it per-vertex
6664 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6665 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6667 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6670 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6671 rsurface.vertex3f_bufferobject = 0;
6672 rsurface.vertex3f_bufferoffset = 0;
6674 case Q3DEFORM_BULGE:
6675 // deform vertex array to make the surface have moving bulges
6676 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6678 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6679 for (j = 0;j < surface->num_vertices;j++)
6681 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6682 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6685 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6686 rsurface.vertex3f_bufferobject = 0;
6687 rsurface.vertex3f_bufferoffset = 0;
6690 // deform vertex array
6691 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6692 VectorScale(deform->parms, scale, waveparms);
6693 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6695 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6696 for (j = 0;j < surface->num_vertices;j++)
6697 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6699 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6700 rsurface.vertex3f_bufferobject = 0;
6701 rsurface.vertex3f_bufferoffset = 0;
6705 // generate texcoords based on the chosen texcoord source
6706 switch(rsurface.texture->tcgen.tcgen)
6709 case Q3TCGEN_TEXTURE:
6710 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6711 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6712 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6714 case Q3TCGEN_LIGHTMAP:
6715 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6716 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6717 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6719 case Q3TCGEN_VECTOR:
6720 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6722 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6723 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)
6725 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6726 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6729 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6730 rsurface.texcoordtexture2f_bufferobject = 0;
6731 rsurface.texcoordtexture2f_bufferoffset = 0;
6733 case Q3TCGEN_ENVIRONMENT:
6734 // make environment reflections using a spheremap
6735 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6737 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6738 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6739 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6740 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6741 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6743 // identical to Q3A's method, but executed in worldspace so
6744 // carried models can be shiny too
6746 float viewer[3], d, reflected[3], worldreflected[3];
6748 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6749 // VectorNormalize(viewer);
6751 d = DotProduct(normal, viewer);
6753 reflected[0] = normal[0]*2*d - viewer[0];
6754 reflected[1] = normal[1]*2*d - viewer[1];
6755 reflected[2] = normal[2]*2*d - viewer[2];
6756 // note: this is proportinal to viewer, so we can normalize later
6758 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6759 VectorNormalize(worldreflected);
6761 // note: this sphere map only uses world x and z!
6762 // so positive and negative y will LOOK THE SAME.
6763 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6764 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6767 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6768 rsurface.texcoordtexture2f_bufferobject = 0;
6769 rsurface.texcoordtexture2f_bufferoffset = 0;
6772 // the only tcmod that needs software vertex processing is turbulent, so
6773 // check for it here and apply the changes if needed
6774 // and we only support that as the first one
6775 // (handling a mixture of turbulent and other tcmods would be problematic
6776 // without punting it entirely to a software path)
6777 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6779 amplitude = rsurface.texture->tcmods[0].parms[1];
6780 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6781 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6783 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6784 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)
6786 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6787 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6790 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6791 rsurface.texcoordtexture2f_bufferobject = 0;
6792 rsurface.texcoordtexture2f_bufferoffset = 0;
6794 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6795 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6796 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6797 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6800 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6803 const msurface_t *surface = texturesurfacelist[0];
6804 const msurface_t *surface2;
6809 // TODO: lock all array ranges before render, rather than on each surface
6810 if (texturenumsurfaces == 1)
6812 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6813 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);
6815 else if (r_batchmode.integer == 2)
6817 #define MAXBATCHTRIANGLES 4096
6818 int batchtriangles = 0;
6819 int batchelements[MAXBATCHTRIANGLES*3];
6820 for (i = 0;i < texturenumsurfaces;i = j)
6822 surface = texturesurfacelist[i];
6824 if (surface->num_triangles > MAXBATCHTRIANGLES)
6826 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);
6829 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6830 batchtriangles = surface->num_triangles;
6831 firstvertex = surface->num_firstvertex;
6832 endvertex = surface->num_firstvertex + surface->num_vertices;
6833 for (;j < texturenumsurfaces;j++)
6835 surface2 = texturesurfacelist[j];
6836 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6838 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6839 batchtriangles += surface2->num_triangles;
6840 firstvertex = min(firstvertex, surface2->num_firstvertex);
6841 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6843 surface2 = texturesurfacelist[j-1];
6844 numvertices = endvertex - firstvertex;
6845 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6848 else if (r_batchmode.integer == 1)
6850 for (i = 0;i < texturenumsurfaces;i = j)
6852 surface = texturesurfacelist[i];
6853 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6854 if (texturesurfacelist[j] != surface2)
6856 surface2 = texturesurfacelist[j-1];
6857 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6858 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6859 GL_LockArrays(surface->num_firstvertex, numvertices);
6860 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6865 for (i = 0;i < texturenumsurfaces;i++)
6867 surface = texturesurfacelist[i];
6868 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6869 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);
6874 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6876 int i, planeindex, vertexindex;
6880 r_waterstate_waterplane_t *p, *bestp;
6881 const msurface_t *surface;
6882 if (r_waterstate.renderingscene)
6884 for (i = 0;i < texturenumsurfaces;i++)
6886 surface = texturesurfacelist[i];
6887 if (lightmaptexunit >= 0)
6888 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6889 if (deluxemaptexunit >= 0)
6890 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6891 // pick the closest matching water plane
6894 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6897 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6899 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6900 d += fabs(PlaneDiff(vert, &p->plane));
6902 if (bestd > d || !bestp)
6910 if (refractiontexunit >= 0)
6911 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6912 if (reflectiontexunit >= 0)
6913 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6917 if (refractiontexunit >= 0)
6918 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6919 if (reflectiontexunit >= 0)
6920 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6922 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
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);
6927 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6931 const msurface_t *surface = texturesurfacelist[0];
6932 const msurface_t *surface2;
6937 // TODO: lock all array ranges before render, rather than on each surface
6938 if (texturenumsurfaces == 1)
6940 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6941 if (deluxemaptexunit >= 0)
6942 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6943 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6944 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6946 else if (r_batchmode.integer == 2)
6948 #define MAXBATCHTRIANGLES 4096
6949 int batchtriangles = 0;
6950 int batchelements[MAXBATCHTRIANGLES*3];
6951 for (i = 0;i < texturenumsurfaces;i = j)
6953 surface = texturesurfacelist[i];
6954 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6955 if (deluxemaptexunit >= 0)
6956 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6958 if (surface->num_triangles > MAXBATCHTRIANGLES)
6960 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);
6963 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6964 batchtriangles = surface->num_triangles;
6965 firstvertex = surface->num_firstvertex;
6966 endvertex = surface->num_firstvertex + surface->num_vertices;
6967 for (;j < texturenumsurfaces;j++)
6969 surface2 = texturesurfacelist[j];
6970 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6972 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6973 batchtriangles += surface2->num_triangles;
6974 firstvertex = min(firstvertex, surface2->num_firstvertex);
6975 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6977 surface2 = texturesurfacelist[j-1];
6978 numvertices = endvertex - firstvertex;
6979 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6982 else if (r_batchmode.integer == 1)
6985 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6986 for (i = 0;i < texturenumsurfaces;i = j)
6988 surface = texturesurfacelist[i];
6989 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6990 if (texturesurfacelist[j] != surface2)
6992 Con_Printf(" %i", j - i);
6995 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6997 for (i = 0;i < texturenumsurfaces;i = j)
6999 surface = texturesurfacelist[i];
7000 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7001 if (deluxemaptexunit >= 0)
7002 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7003 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7004 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
7007 Con_Printf(" %i", j - i);
7009 surface2 = texturesurfacelist[j-1];
7010 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7011 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7012 GL_LockArrays(surface->num_firstvertex, numvertices);
7013 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7021 for (i = 0;i < texturenumsurfaces;i++)
7023 surface = texturesurfacelist[i];
7024 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7025 if (deluxemaptexunit >= 0)
7026 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7027 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7028 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);
7033 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7036 int texturesurfaceindex;
7037 if (r_showsurfaces.integer == 2)
7039 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7041 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7042 for (j = 0;j < surface->num_triangles;j++)
7044 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7045 GL_Color(f, f, f, 1);
7046 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7052 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7054 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7055 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7056 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);
7057 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7058 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7063 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7065 int texturesurfaceindex;
7069 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7071 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7072 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)
7080 rsurface.lightmapcolor4f = rsurface.array_color4f;
7081 rsurface.lightmapcolor4f_bufferobject = 0;
7082 rsurface.lightmapcolor4f_bufferoffset = 0;
7085 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7087 int texturesurfaceindex;
7093 if (rsurface.lightmapcolor4f)
7095 // generate color arrays for the surfaces in this list
7096 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7098 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7099 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)
7101 f = RSurf_FogVertex(v);
7111 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7113 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7114 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)
7116 f = RSurf_FogVertex(v);
7124 rsurface.lightmapcolor4f = rsurface.array_color4f;
7125 rsurface.lightmapcolor4f_bufferobject = 0;
7126 rsurface.lightmapcolor4f_bufferoffset = 0;
7129 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7131 int texturesurfaceindex;
7137 if (!rsurface.lightmapcolor4f)
7139 // generate color arrays for the surfaces in this list
7140 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7142 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7143 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)
7145 f = RSurf_FogVertex(v);
7146 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7147 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7148 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7152 rsurface.lightmapcolor4f = rsurface.array_color4f;
7153 rsurface.lightmapcolor4f_bufferobject = 0;
7154 rsurface.lightmapcolor4f_bufferoffset = 0;
7157 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7159 int texturesurfaceindex;
7163 if (!rsurface.lightmapcolor4f)
7165 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7167 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7168 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)
7176 rsurface.lightmapcolor4f = rsurface.array_color4f;
7177 rsurface.lightmapcolor4f_bufferobject = 0;
7178 rsurface.lightmapcolor4f_bufferoffset = 0;
7181 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7183 int texturesurfaceindex;
7187 if (!rsurface.lightmapcolor4f)
7189 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7191 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7192 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)
7194 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7195 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7196 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7200 rsurface.lightmapcolor4f = rsurface.array_color4f;
7201 rsurface.lightmapcolor4f_bufferobject = 0;
7202 rsurface.lightmapcolor4f_bufferoffset = 0;
7205 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7208 rsurface.lightmapcolor4f = NULL;
7209 rsurface.lightmapcolor4f_bufferobject = 0;
7210 rsurface.lightmapcolor4f_bufferoffset = 0;
7211 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7212 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7213 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7214 GL_Color(r, g, b, a);
7215 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7218 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7220 // TODO: optimize applyfog && applycolor case
7221 // just apply fog if necessary, and tint the fog color array if necessary
7222 rsurface.lightmapcolor4f = NULL;
7223 rsurface.lightmapcolor4f_bufferobject = 0;
7224 rsurface.lightmapcolor4f_bufferoffset = 0;
7225 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7226 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7227 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7228 GL_Color(r, g, b, a);
7229 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7232 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7234 int texturesurfaceindex;
7238 if (texturesurfacelist[0]->lightmapinfo)
7240 // generate color arrays for the surfaces in this list
7241 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7243 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7244 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7246 if (surface->lightmapinfo->samples)
7248 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7249 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7250 VectorScale(lm, scale, c);
7251 if (surface->lightmapinfo->styles[1] != 255)
7253 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7255 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7256 VectorMA(c, scale, lm, c);
7257 if (surface->lightmapinfo->styles[2] != 255)
7260 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7261 VectorMA(c, scale, lm, c);
7262 if (surface->lightmapinfo->styles[3] != 255)
7265 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7266 VectorMA(c, scale, lm, c);
7276 rsurface.lightmapcolor4f = rsurface.array_color4f;
7277 rsurface.lightmapcolor4f_bufferobject = 0;
7278 rsurface.lightmapcolor4f_bufferoffset = 0;
7282 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7283 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7284 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7286 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7287 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7288 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7289 GL_Color(r, g, b, a);
7290 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7293 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7295 int texturesurfaceindex;
7302 vec3_t ambientcolor;
7303 vec3_t diffusecolor;
7307 VectorCopy(rsurface.modellight_lightdir, lightdir);
7308 f = 0.5f * r_refdef.lightmapintensity;
7309 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7310 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7311 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7312 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7313 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7314 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7316 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7318 // generate color arrays for the surfaces in this list
7319 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7321 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7322 int numverts = surface->num_vertices;
7323 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7324 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7325 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7326 // q3-style directional shading
7327 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7329 if ((f = DotProduct(n, lightdir)) > 0)
7330 VectorMA(ambientcolor, f, diffusecolor, c);
7332 VectorCopy(ambientcolor, c);
7340 rsurface.lightmapcolor4f = rsurface.array_color4f;
7341 rsurface.lightmapcolor4f_bufferobject = 0;
7342 rsurface.lightmapcolor4f_bufferoffset = 0;
7343 *applycolor = false;
7347 *r = ambientcolor[0];
7348 *g = ambientcolor[1];
7349 *b = ambientcolor[2];
7350 rsurface.lightmapcolor4f = NULL;
7351 rsurface.lightmapcolor4f_bufferobject = 0;
7352 rsurface.lightmapcolor4f_bufferoffset = 0;
7356 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7358 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7359 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7360 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7361 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7362 GL_Color(r, g, b, a);
7363 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7366 void RSurf_SetupDepthAndCulling(void)
7368 // submodels are biased to avoid z-fighting with world surfaces that they
7369 // may be exactly overlapping (avoids z-fighting artifacts on certain
7370 // doors and things in Quake maps)
7371 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7372 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7373 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7374 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7377 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7379 // transparent sky would be ridiculous
7380 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7382 R_SetupGenericShader(false);
7383 skyrenderlater = true;
7384 RSurf_SetupDepthAndCulling();
7386 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7387 // skymasking on them, and Quake3 never did sky masking (unlike
7388 // software Quake and software Quake2), so disable the sky masking
7389 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7390 // and skymasking also looks very bad when noclipping outside the
7391 // level, so don't use it then either.
7392 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7394 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7395 R_Mesh_ColorPointer(NULL, 0, 0);
7396 R_Mesh_ResetTextureState();
7397 if (skyrendermasked)
7399 R_SetupDepthOrShadowShader();
7400 // depth-only (masking)
7401 GL_ColorMask(0,0,0,0);
7402 // just to make sure that braindead drivers don't draw
7403 // anything despite that colormask...
7404 GL_BlendFunc(GL_ZERO, GL_ONE);
7408 R_SetupGenericShader(false);
7410 GL_BlendFunc(GL_ONE, GL_ZERO);
7412 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7413 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7414 if (skyrendermasked)
7415 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7417 R_Mesh_ResetTextureState();
7418 GL_Color(1, 1, 1, 1);
7421 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7423 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7426 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7427 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7428 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7429 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7430 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7431 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7432 if (rsurface.texture->backgroundcurrentskinframe)
7434 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7435 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7436 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7437 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7439 if(rsurface.texture->colormapping)
7441 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7442 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7444 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7445 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7446 R_Mesh_ColorPointer(NULL, 0, 0);
7448 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7450 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7452 // render background
7453 GL_BlendFunc(GL_ONE, GL_ZERO);
7455 GL_AlphaTest(false);
7457 GL_Color(1, 1, 1, 1);
7458 R_Mesh_ColorPointer(NULL, 0, 0);
7460 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7461 if (r_glsl_permutation)
7463 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7464 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7465 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7466 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7467 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7468 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7469 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);
7471 GL_LockArrays(0, 0);
7473 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7474 GL_DepthMask(false);
7475 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7476 R_Mesh_ColorPointer(NULL, 0, 0);
7478 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7479 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7480 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7483 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7484 if (!r_glsl_permutation)
7487 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7488 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7489 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7490 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7491 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7492 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7494 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7496 GL_BlendFunc(GL_ONE, GL_ZERO);
7498 GL_AlphaTest(false);
7502 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7503 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7504 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7507 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7509 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7510 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);
7512 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7516 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7517 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);
7519 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7521 GL_LockArrays(0, 0);
7524 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7526 // OpenGL 1.3 path - anything not completely ancient
7527 int texturesurfaceindex;
7528 qboolean applycolor;
7532 const texturelayer_t *layer;
7533 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7535 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7538 int layertexrgbscale;
7539 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7541 if (layerindex == 0)
7545 GL_AlphaTest(false);
7546 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7549 GL_DepthMask(layer->depthmask && writedepth);
7550 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7551 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7553 layertexrgbscale = 4;
7554 VectorScale(layer->color, 0.25f, layercolor);
7556 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7558 layertexrgbscale = 2;
7559 VectorScale(layer->color, 0.5f, layercolor);
7563 layertexrgbscale = 1;
7564 VectorScale(layer->color, 1.0f, layercolor);
7566 layercolor[3] = layer->color[3];
7567 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7568 R_Mesh_ColorPointer(NULL, 0, 0);
7569 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7570 switch (layer->type)
7572 case TEXTURELAYERTYPE_LITTEXTURE:
7573 memset(&m, 0, sizeof(m));
7574 m.tex[0] = R_GetTexture(r_texture_white);
7575 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7576 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7577 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7578 m.tex[1] = R_GetTexture(layer->texture);
7579 m.texmatrix[1] = layer->texmatrix;
7580 m.texrgbscale[1] = layertexrgbscale;
7581 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7582 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7583 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7584 R_Mesh_TextureState(&m);
7585 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7586 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7587 else if (rsurface.uselightmaptexture)
7588 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7590 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7592 case TEXTURELAYERTYPE_TEXTURE:
7593 memset(&m, 0, sizeof(m));
7594 m.tex[0] = R_GetTexture(layer->texture);
7595 m.texmatrix[0] = layer->texmatrix;
7596 m.texrgbscale[0] = layertexrgbscale;
7597 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7598 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7599 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7600 R_Mesh_TextureState(&m);
7601 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7603 case TEXTURELAYERTYPE_FOG:
7604 memset(&m, 0, sizeof(m));
7605 m.texrgbscale[0] = layertexrgbscale;
7608 m.tex[0] = R_GetTexture(layer->texture);
7609 m.texmatrix[0] = layer->texmatrix;
7610 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7611 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7612 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7614 R_Mesh_TextureState(&m);
7615 // generate a color array for the fog pass
7616 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7617 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7623 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7624 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)
7626 f = 1 - RSurf_FogVertex(v);
7627 c[0] = layercolor[0];
7628 c[1] = layercolor[1];
7629 c[2] = layercolor[2];
7630 c[3] = f * layercolor[3];
7633 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7636 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7638 GL_LockArrays(0, 0);
7641 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7643 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7644 GL_AlphaTest(false);
7648 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7650 // OpenGL 1.1 - crusty old voodoo path
7651 int texturesurfaceindex;
7655 const texturelayer_t *layer;
7656 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7658 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7660 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7662 if (layerindex == 0)
7666 GL_AlphaTest(false);
7667 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7670 GL_DepthMask(layer->depthmask && writedepth);
7671 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7672 R_Mesh_ColorPointer(NULL, 0, 0);
7673 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7674 switch (layer->type)
7676 case TEXTURELAYERTYPE_LITTEXTURE:
7677 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7679 // two-pass lit texture with 2x rgbscale
7680 // first the lightmap pass
7681 memset(&m, 0, sizeof(m));
7682 m.tex[0] = R_GetTexture(r_texture_white);
7683 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7684 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7685 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7686 R_Mesh_TextureState(&m);
7687 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7688 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7689 else if (rsurface.uselightmaptexture)
7690 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7692 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7693 GL_LockArrays(0, 0);
7694 // then apply the texture to it
7695 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7696 memset(&m, 0, sizeof(m));
7697 m.tex[0] = R_GetTexture(layer->texture);
7698 m.texmatrix[0] = layer->texmatrix;
7699 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7700 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7701 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7702 R_Mesh_TextureState(&m);
7703 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);
7707 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7708 memset(&m, 0, sizeof(m));
7709 m.tex[0] = R_GetTexture(layer->texture);
7710 m.texmatrix[0] = layer->texmatrix;
7711 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7712 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7713 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7714 R_Mesh_TextureState(&m);
7715 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7716 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);
7718 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);
7721 case TEXTURELAYERTYPE_TEXTURE:
7722 // singletexture unlit texture with transparency support
7723 memset(&m, 0, sizeof(m));
7724 m.tex[0] = R_GetTexture(layer->texture);
7725 m.texmatrix[0] = layer->texmatrix;
7726 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7727 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7728 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7729 R_Mesh_TextureState(&m);
7730 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);
7732 case TEXTURELAYERTYPE_FOG:
7733 // singletexture fogging
7734 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7737 memset(&m, 0, sizeof(m));
7738 m.tex[0] = R_GetTexture(layer->texture);
7739 m.texmatrix[0] = layer->texmatrix;
7740 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7741 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7742 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7743 R_Mesh_TextureState(&m);
7746 R_Mesh_ResetTextureState();
7747 // generate a color array for the fog pass
7748 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7754 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7755 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)
7757 f = 1 - RSurf_FogVertex(v);
7758 c[0] = layer->color[0];
7759 c[1] = layer->color[1];
7760 c[2] = layer->color[2];
7761 c[3] = f * layer->color[3];
7764 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7767 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7769 GL_LockArrays(0, 0);
7772 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7774 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7775 GL_AlphaTest(false);
7779 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7783 GL_AlphaTest(false);
7784 R_Mesh_ColorPointer(NULL, 0, 0);
7785 R_Mesh_ResetTextureState();
7786 R_SetupGenericShader(false);
7788 if(rsurface.texture && rsurface.texture->currentskinframe)
7790 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7791 c[3] *= rsurface.texture->currentalpha;
7801 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7803 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7804 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7805 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7808 // brighten it up (as texture value 127 means "unlit")
7809 c[0] *= 2 * r_refdef.view.colorscale;
7810 c[1] *= 2 * r_refdef.view.colorscale;
7811 c[2] *= 2 * r_refdef.view.colorscale;
7813 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7814 c[3] *= r_wateralpha.value;
7816 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7818 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7819 GL_DepthMask(false);
7821 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7823 GL_BlendFunc(GL_ONE, GL_ONE);
7824 GL_DepthMask(false);
7826 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7828 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7829 GL_DepthMask(false);
7831 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7833 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7834 GL_DepthMask(false);
7838 GL_BlendFunc(GL_ONE, GL_ZERO);
7839 GL_DepthMask(writedepth);
7842 rsurface.lightmapcolor4f = NULL;
7844 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7846 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7848 rsurface.lightmapcolor4f = NULL;
7849 rsurface.lightmapcolor4f_bufferobject = 0;
7850 rsurface.lightmapcolor4f_bufferoffset = 0;
7852 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7854 qboolean applycolor = true;
7857 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7859 r_refdef.lightmapintensity = 1;
7860 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7861 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7865 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7867 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7868 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7869 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7872 if(!rsurface.lightmapcolor4f)
7873 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7875 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7876 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7877 if(r_refdef.fogenabled)
7878 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7880 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7881 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7884 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7887 RSurf_SetupDepthAndCulling();
7888 if (r_showsurfaces.integer == 3)
7889 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7890 else if (r_glsl.integer && vid.support.arb_fragment_shader)
7891 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7892 else if (gl_combine.integer && r_textureunits.integer >= 2)
7893 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7895 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7899 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7902 RSurf_SetupDepthAndCulling();
7903 if (r_showsurfaces.integer == 3)
7904 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7905 else if (r_glsl.integer && vid.support.arb_fragment_shader)
7906 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7907 else if (gl_combine.integer && r_textureunits.integer >= 2)
7908 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7910 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7914 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7917 int texturenumsurfaces, endsurface;
7919 const msurface_t *surface;
7920 const msurface_t *texturesurfacelist[1024];
7922 // if the model is static it doesn't matter what value we give for
7923 // wantnormals and wanttangents, so this logic uses only rules applicable
7924 // to a model, knowing that they are meaningless otherwise
7925 if (ent == r_refdef.scene.worldentity)
7926 RSurf_ActiveWorldEntity();
7927 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7928 RSurf_ActiveModelEntity(ent, false, false);
7930 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && vid.support.arb_fragment_shader);
7932 for (i = 0;i < numsurfaces;i = j)
7935 surface = rsurface.modelsurfaces + surfacelist[i];
7936 texture = surface->texture;
7937 rsurface.texture = R_GetCurrentTexture(texture);
7938 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7939 // scan ahead until we find a different texture
7940 endsurface = min(i + 1024, numsurfaces);
7941 texturenumsurfaces = 0;
7942 texturesurfacelist[texturenumsurfaces++] = surface;
7943 for (;j < endsurface;j++)
7945 surface = rsurface.modelsurfaces + surfacelist[j];
7946 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7948 texturesurfacelist[texturenumsurfaces++] = surface;
7950 // render the range of surfaces
7951 if (ent == r_refdef.scene.worldentity)
7952 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7954 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7956 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7957 GL_AlphaTest(false);
7960 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7962 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7966 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7968 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7970 RSurf_SetupDepthAndCulling();
7971 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7972 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7974 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7976 RSurf_SetupDepthAndCulling();
7977 GL_AlphaTest(false);
7978 R_Mesh_ColorPointer(NULL, 0, 0);
7979 R_Mesh_ResetTextureState();
7980 R_SetupGenericShader(false);
7981 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7983 GL_BlendFunc(GL_ONE, GL_ZERO);
7984 GL_Color(0, 0, 0, 1);
7985 GL_DepthTest(writedepth);
7986 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7988 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7990 RSurf_SetupDepthAndCulling();
7991 GL_AlphaTest(false);
7992 R_Mesh_ColorPointer(NULL, 0, 0);
7993 R_Mesh_ResetTextureState();
7994 R_SetupGenericShader(false);
7995 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7997 GL_BlendFunc(GL_ONE, GL_ZERO);
7999 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8001 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8002 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8003 else if (!rsurface.texture->currentnumlayers)
8005 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8007 // transparent surfaces get pushed off into the transparent queue
8008 int surfacelistindex;
8009 const msurface_t *surface;
8010 vec3_t tempcenter, center;
8011 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8013 surface = texturesurfacelist[surfacelistindex];
8014 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8015 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8016 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8017 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8018 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8023 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8024 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8029 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8033 // break the surface list down into batches by texture and use of lightmapping
8034 for (i = 0;i < numsurfaces;i = j)
8037 // texture is the base texture pointer, rsurface.texture is the
8038 // current frame/skin the texture is directing us to use (for example
8039 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8040 // use skin 1 instead)
8041 texture = surfacelist[i]->texture;
8042 rsurface.texture = R_GetCurrentTexture(texture);
8043 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8044 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8046 // if this texture is not the kind we want, skip ahead to the next one
8047 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8051 // simply scan ahead until we find a different texture or lightmap state
8052 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8054 // render the range of surfaces
8055 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
8059 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
8064 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8066 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8068 RSurf_SetupDepthAndCulling();
8069 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8070 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8072 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8074 RSurf_SetupDepthAndCulling();
8075 GL_AlphaTest(false);
8076 R_Mesh_ColorPointer(NULL, 0, 0);
8077 R_Mesh_ResetTextureState();
8078 R_SetupGenericShader(false);
8079 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8081 GL_BlendFunc(GL_ONE, GL_ZERO);
8082 GL_Color(0, 0, 0, 1);
8083 GL_DepthTest(writedepth);
8084 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8086 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8088 RSurf_SetupDepthAndCulling();
8089 GL_AlphaTest(false);
8090 R_Mesh_ColorPointer(NULL, 0, 0);
8091 R_Mesh_ResetTextureState();
8092 R_SetupGenericShader(false);
8093 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8095 GL_BlendFunc(GL_ONE, GL_ZERO);
8097 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8099 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8100 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8101 else if (!rsurface.texture->currentnumlayers)
8103 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8105 // transparent surfaces get pushed off into the transparent queue
8106 int surfacelistindex;
8107 const msurface_t *surface;
8108 vec3_t tempcenter, center;
8109 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8111 surface = texturesurfacelist[surfacelistindex];
8112 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8113 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8114 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8115 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8116 if (queueentity->transparent_offset) // transparent offset
8118 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8119 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8120 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8122 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8127 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8128 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8133 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8137 // break the surface list down into batches by texture and use of lightmapping
8138 for (i = 0;i < numsurfaces;i = j)
8141 // texture is the base texture pointer, rsurface.texture is the
8142 // current frame/skin the texture is directing us to use (for example
8143 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8144 // use skin 1 instead)
8145 texture = surfacelist[i]->texture;
8146 rsurface.texture = R_GetCurrentTexture(texture);
8147 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8148 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8150 // if this texture is not the kind we want, skip ahead to the next one
8151 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8155 // simply scan ahead until we find a different texture or lightmap state
8156 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8158 // render the range of surfaces
8159 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8163 float locboxvertex3f[6*4*3] =
8165 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8166 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8167 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8168 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8169 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8170 1,0,0, 0,0,0, 0,1,0, 1,1,0
8173 unsigned short locboxelements[6*2*3] =
8183 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8186 cl_locnode_t *loc = (cl_locnode_t *)ent;
8188 float vertex3f[6*4*3];
8190 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8191 GL_DepthMask(false);
8192 GL_DepthRange(0, 1);
8193 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8195 GL_CullFace(GL_NONE);
8196 R_Mesh_Matrix(&identitymatrix);
8198 R_Mesh_VertexPointer(vertex3f, 0, 0);
8199 R_Mesh_ColorPointer(NULL, 0, 0);
8200 R_Mesh_ResetTextureState();
8201 R_SetupGenericShader(false);
8204 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8205 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8206 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8207 surfacelist[0] < 0 ? 0.5f : 0.125f);
8209 if (VectorCompare(loc->mins, loc->maxs))
8211 VectorSet(size, 2, 2, 2);
8212 VectorMA(loc->mins, -0.5f, size, mins);
8216 VectorCopy(loc->mins, mins);
8217 VectorSubtract(loc->maxs, loc->mins, size);
8220 for (i = 0;i < 6*4*3;)
8221 for (j = 0;j < 3;j++, i++)
8222 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8224 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8227 void R_DrawLocs(void)
8230 cl_locnode_t *loc, *nearestloc;
8232 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8233 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8235 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8236 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8240 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8242 if (decalsystem->decals)
8243 Mem_Free(decalsystem->decals);
8244 memset(decalsystem, 0, sizeof(*decalsystem));
8247 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)
8254 // expand or initialize the system
8255 if (decalsystem->maxdecals <= decalsystem->numdecals)
8257 decalsystem_t old = *decalsystem;
8258 qboolean useshortelements;
8259 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8260 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8261 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)));
8262 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8263 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8264 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8265 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8266 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8267 if (decalsystem->numdecals)
8268 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8270 Mem_Free(old.decals);
8271 for (i = 0;i < decalsystem->maxdecals*3;i++)
8272 decalsystem->element3i[i] = i;
8273 if (useshortelements)
8274 for (i = 0;i < decalsystem->maxdecals*3;i++)
8275 decalsystem->element3s[i] = i;
8278 // grab a decal and search for another free slot for the next one
8279 maxdecals = decalsystem->maxdecals;
8280 decals = decalsystem->decals;
8281 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8282 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8284 decalsystem->freedecal = i;
8285 if (decalsystem->numdecals <= i)
8286 decalsystem->numdecals = i + 1;
8288 // initialize the decal
8290 decal->triangleindex = triangleindex;
8291 decal->surfaceindex = surfaceindex;
8292 decal->decalsequence = decalsequence;
8293 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8294 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8295 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8296 decal->color4ub[0][3] = 255;
8297 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8298 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8299 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8300 decal->color4ub[1][3] = 255;
8301 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8302 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8303 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8304 decal->color4ub[2][3] = 255;
8305 decal->vertex3f[0][0] = v0[0];
8306 decal->vertex3f[0][1] = v0[1];
8307 decal->vertex3f[0][2] = v0[2];
8308 decal->vertex3f[1][0] = v1[0];
8309 decal->vertex3f[1][1] = v1[1];
8310 decal->vertex3f[1][2] = v1[2];
8311 decal->vertex3f[2][0] = v2[0];
8312 decal->vertex3f[2][1] = v2[1];
8313 decal->vertex3f[2][2] = v2[2];
8314 decal->texcoord2f[0][0] = t0[0];
8315 decal->texcoord2f[0][1] = t0[1];
8316 decal->texcoord2f[1][0] = t1[0];
8317 decal->texcoord2f[1][1] = t1[1];
8318 decal->texcoord2f[2][0] = t2[0];
8319 decal->texcoord2f[2][1] = t2[1];
8322 extern cvar_t cl_decals_bias;
8323 extern cvar_t cl_decals_models;
8324 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8325 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)
8327 matrix4x4_t projection;
8328 decalsystem_t *decalsystem;
8331 const float *vertex3f;
8332 const msurface_t *surface;
8333 const msurface_t *surfaces;
8334 const int *surfacelist;
8335 const texture_t *texture;
8339 int surfacelistindex;
8342 int decalsurfaceindex;
8347 float localorigin[3];
8348 float localnormal[3];
8359 float points[2][9][3];
8363 decalsystem = &ent->decalsystem;
8365 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8367 R_DecalSystem_Reset(&ent->decalsystem);
8371 if (!model->brush.data_nodes && !cl_decals_models.integer)
8373 if (decalsystem->model)
8374 R_DecalSystem_Reset(decalsystem);
8378 if (decalsystem->model != model)
8379 R_DecalSystem_Reset(decalsystem);
8380 decalsystem->model = model;
8382 RSurf_ActiveModelEntity(ent, false, false);
8384 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8385 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8386 VectorNormalize(localnormal);
8387 localsize = worldsize*rsurface.inversematrixscale;
8388 ilocalsize = 1.0f / localsize;
8389 localmins[0] = localorigin[0] - localsize;
8390 localmins[1] = localorigin[1] - localsize;
8391 localmins[2] = localorigin[2] - localsize;
8392 localmaxs[0] = localorigin[0] + localsize;
8393 localmaxs[1] = localorigin[1] + localsize;
8394 localmaxs[2] = localorigin[2] + localsize;
8396 //VectorCopy(localnormal, planes[4]);
8397 //VectorVectors(planes[4], planes[2], planes[0]);
8398 AnglesFromVectors(angles, localnormal, NULL, false);
8399 AngleVectors(angles, planes[0], planes[2], planes[4]);
8400 VectorNegate(planes[0], planes[1]);
8401 VectorNegate(planes[2], planes[3]);
8402 VectorNegate(planes[4], planes[5]);
8403 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8404 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8405 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8406 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8407 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8408 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8413 matrix4x4_t forwardprojection;
8414 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8415 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8420 float projectionvector[4][3];
8421 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8422 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8423 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8424 projectionvector[0][0] = planes[0][0] * ilocalsize;
8425 projectionvector[0][1] = planes[1][0] * ilocalsize;
8426 projectionvector[0][2] = planes[2][0] * ilocalsize;
8427 projectionvector[1][0] = planes[0][1] * ilocalsize;
8428 projectionvector[1][1] = planes[1][1] * ilocalsize;
8429 projectionvector[1][2] = planes[2][1] * ilocalsize;
8430 projectionvector[2][0] = planes[0][2] * ilocalsize;
8431 projectionvector[2][1] = planes[1][2] * ilocalsize;
8432 projectionvector[2][2] = planes[2][2] * ilocalsize;
8433 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8434 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8435 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8436 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8440 dynamic = model->surfmesh.isanimated;
8441 vertex3f = rsurface.modelvertex3f;
8442 numsurfacelist = model->nummodelsurfaces;
8443 surfacelist = model->sortedmodelsurfaces;
8444 surfaces = model->data_surfaces;
8445 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8447 surfaceindex = surfacelist[surfacelistindex];
8448 surface = surfaces + surfaceindex;
8449 // skip transparent surfaces
8450 texture = surface->texture;
8451 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8453 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8455 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8457 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8458 numvertices = surface->num_vertices;
8459 numtriangles = surface->num_triangles;
8460 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8462 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8464 index = 3*e[cornerindex];
8465 VectorCopy(vertex3f + index, v[cornerindex]);
8468 //TriangleNormal(v[0], v[1], v[2], normal);
8469 //if (DotProduct(normal, localnormal) < 0.0f)
8471 // clip by each of the box planes formed from the projection matrix
8472 // if anything survives, we emit the decal
8473 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]);
8476 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]);
8479 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]);
8482 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]);
8485 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]);
8488 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]);
8491 // some part of the triangle survived, so we have to accept it...
8494 // dynamic always uses the original triangle
8496 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8498 index = 3*e[cornerindex];
8499 VectorCopy(vertex3f + index, v[cornerindex]);
8502 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8504 // convert vertex positions to texcoords
8505 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8506 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8507 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8508 // calculate distance fade from the projection origin
8509 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8510 f = bound(0.0f, f, 1.0f);
8511 c[cornerindex][0] = r * f;
8512 c[cornerindex][1] = g * f;
8513 c[cornerindex][2] = b * f;
8514 c[cornerindex][3] = 1.0f;
8515 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8518 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);
8520 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8521 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);
8526 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8527 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)
8529 int renderentityindex;
8532 entity_render_t *ent;
8534 if (!cl_decals_newsystem.integer)
8537 worldmins[0] = worldorigin[0] - worldsize;
8538 worldmins[1] = worldorigin[1] - worldsize;
8539 worldmins[2] = worldorigin[2] - worldsize;
8540 worldmaxs[0] = worldorigin[0] + worldsize;
8541 worldmaxs[1] = worldorigin[1] + worldsize;
8542 worldmaxs[2] = worldorigin[2] + worldsize;
8544 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8546 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8548 ent = r_refdef.scene.entities[renderentityindex];
8549 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8552 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8556 typedef struct r_decalsystem_splatqueue_s
8565 r_decalsystem_splatqueue_t;
8567 int r_decalsystem_numqueued = 0;
8568 #define MAX_DECALSYSTEM_QUEUE 1024
8569 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8571 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)
8573 r_decalsystem_splatqueue_t *queue;
8575 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8578 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8579 VectorCopy(worldorigin, queue->worldorigin);
8580 VectorCopy(worldnormal, queue->worldnormal);
8581 Vector4Set(queue->color, r, g, b, a);
8582 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8583 queue->worldsize = worldsize;
8584 queue->decalsequence = cl.decalsequence++;
8587 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8590 r_decalsystem_splatqueue_t *queue;
8592 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8593 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);
8594 r_decalsystem_numqueued = 0;
8597 extern cvar_t cl_decals_max;
8598 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8601 decalsystem_t *decalsystem = &ent->decalsystem;
8608 if (!decalsystem->numdecals)
8611 if (r_showsurfaces.integer)
8614 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8616 R_DecalSystem_Reset(decalsystem);
8620 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
8621 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
8623 if (decalsystem->lastupdatetime)
8624 frametime = (cl.time - decalsystem->lastupdatetime);
8627 decalsystem->lastupdatetime = cl.time;
8628 decal = decalsystem->decals;
8629 numdecals = decalsystem->numdecals;
8631 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8633 if (decal->color4ub[0][3])
8635 decal->lived += frametime;
8636 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
8638 memset(decal, 0, sizeof(*decal));
8639 if (decalsystem->freedecal > i)
8640 decalsystem->freedecal = i;
8644 decal = decalsystem->decals;
8645 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
8648 // collapse the array by shuffling the tail decals into the gaps
8651 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
8652 decalsystem->freedecal++;
8653 if (decalsystem->freedecal == numdecals)
8655 decal[decalsystem->freedecal] = decal[--numdecals];
8658 decalsystem->numdecals = numdecals;
8662 // if there are no decals left, reset decalsystem
8663 R_DecalSystem_Reset(decalsystem);
8667 extern skinframe_t *decalskinframe;
8668 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8671 decalsystem_t *decalsystem = &ent->decalsystem;
8681 const unsigned char *surfacevisible = r_refdef.viewcache.world_surfacevisible;
8684 numdecals = decalsystem->numdecals;
8688 if (r_showsurfaces.integer)
8691 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8693 R_DecalSystem_Reset(decalsystem);
8697 // if the model is static it doesn't matter what value we give for
8698 // wantnormals and wanttangents, so this logic uses only rules applicable
8699 // to a model, knowing that they are meaningless otherwise
8700 if (ent == r_refdef.scene.worldentity)
8701 RSurf_ActiveWorldEntity();
8703 RSurf_ActiveModelEntity(ent, false, false);
8705 decalsystem->lastupdatetime = cl.time;
8706 decal = decalsystem->decals;
8708 fadedelay = cl_decals_time.value;
8709 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
8711 // update vertex positions for animated models
8712 v3f = decalsystem->vertex3f;
8713 c4f = decalsystem->color4f;
8714 t2f = decalsystem->texcoord2f;
8715 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8717 if (!decal->color4ub[0][3])
8720 if (decal->surfaceindex >= 0 && !surfacevisible[decal->surfaceindex])
8723 // update color values for fading decals
8724 if (decal->lived >= cl_decals_time.value)
8726 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
8727 alpha *= (1.0f/255.0f);
8730 alpha = 1.0f/255.0f;
8732 c4f[ 0] = decal->color4ub[0][0] * alpha;
8733 c4f[ 1] = decal->color4ub[0][1] * alpha;
8734 c4f[ 2] = decal->color4ub[0][2] * alpha;
8736 c4f[ 4] = decal->color4ub[1][0] * alpha;
8737 c4f[ 5] = decal->color4ub[1][1] * alpha;
8738 c4f[ 6] = decal->color4ub[1][2] * alpha;
8740 c4f[ 8] = decal->color4ub[2][0] * alpha;
8741 c4f[ 9] = decal->color4ub[2][1] * alpha;
8742 c4f[10] = decal->color4ub[2][2] * alpha;
8745 t2f[0] = decal->texcoord2f[0][0];
8746 t2f[1] = decal->texcoord2f[0][1];
8747 t2f[2] = decal->texcoord2f[1][0];
8748 t2f[3] = decal->texcoord2f[1][1];
8749 t2f[4] = decal->texcoord2f[2][0];
8750 t2f[5] = decal->texcoord2f[2][1];
8752 // update vertex positions for animated models
8753 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8755 e = rsurface.modelelement3i + 3*decal->triangleindex;
8756 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8757 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8758 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8762 VectorCopy(decal->vertex3f[0], v3f);
8763 VectorCopy(decal->vertex3f[1], v3f + 3);
8764 VectorCopy(decal->vertex3f[2], v3f + 6);
8775 r_refdef.stats.drawndecals += numtris;
8776 // now render the decals all at once
8777 // (this assumes they all use one particle font texture!)
8778 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);
8779 R_Mesh_ResetTextureState();
8780 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8781 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8782 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8783 R_SetupGenericShader(true);
8784 GL_DepthMask(false);
8785 GL_DepthRange(0, 1);
8786 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
8788 GL_CullFace(GL_NONE);
8789 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8790 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8791 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8792 GL_LockArrays(0, numtris * 3);
8793 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
8794 GL_LockArrays(0, 0);
8798 static void R_DrawModelDecals(void)
8802 // fade faster when there are too many decals
8803 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
8804 for (i = 0;i < r_refdef.scene.numentities;i++)
8805 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
8807 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
8808 for (i = 0;i < r_refdef.scene.numentities;i++)
8809 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
8810 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
8812 R_DecalSystem_ApplySplatEntitiesQueue();
8814 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
8815 for (i = 0;i < r_refdef.scene.numentities;i++)
8816 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
8818 r_refdef.stats.totaldecals += numdecals;
8820 if (r_showsurfaces.integer)
8823 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
8825 if (!r_drawentities.integer)
8828 for (i = 0;i < r_refdef.scene.numentities;i++)
8830 if (!r_refdef.viewcache.entityvisible[i])
8832 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
8833 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
8837 void R_DrawDebugModel(void)
8839 entity_render_t *ent = rsurface.entity;
8840 int i, j, k, l, flagsmask;
8841 const int *elements;
8843 const msurface_t *surface;
8844 dp_model_t *model = ent->model;
8847 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8849 R_Mesh_ColorPointer(NULL, 0, 0);
8850 R_Mesh_ResetTextureState();
8851 R_SetupGenericShader(false);
8852 GL_DepthRange(0, 1);
8853 GL_DepthTest(!r_showdisabledepthtest.integer);
8854 GL_DepthMask(false);
8855 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8857 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8859 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8860 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8862 if (brush->colbrushf && brush->colbrushf->numtriangles)
8864 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8865 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);
8866 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8869 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8871 if (surface->num_collisiontriangles)
8873 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8874 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);
8875 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8880 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8882 if (r_showtris.integer || r_shownormals.integer)
8884 if (r_showdisabledepthtest.integer)
8886 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8887 GL_DepthMask(false);
8891 GL_BlendFunc(GL_ONE, GL_ZERO);
8894 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8896 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8898 rsurface.texture = R_GetCurrentTexture(surface->texture);
8899 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8901 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8902 if (r_showtris.value > 0)
8904 if (!rsurface.texture->currentlayers->depthmask)
8905 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8906 else if (ent == r_refdef.scene.worldentity)
8907 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8909 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8910 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8911 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8912 R_Mesh_ColorPointer(NULL, 0, 0);
8913 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8914 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8915 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8916 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);
8917 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8920 if (r_shownormals.value < 0)
8923 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8925 VectorCopy(rsurface.vertex3f + l * 3, v);
8926 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8927 qglVertex3f(v[0], v[1], v[2]);
8928 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8929 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8930 qglVertex3f(v[0], v[1], v[2]);
8935 if (r_shownormals.value > 0)
8938 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8940 VectorCopy(rsurface.vertex3f + l * 3, v);
8941 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8942 qglVertex3f(v[0], v[1], v[2]);
8943 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8944 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8945 qglVertex3f(v[0], v[1], v[2]);
8950 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8952 VectorCopy(rsurface.vertex3f + l * 3, v);
8953 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8954 qglVertex3f(v[0], v[1], v[2]);
8955 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8956 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8957 qglVertex3f(v[0], v[1], v[2]);
8962 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8964 VectorCopy(rsurface.vertex3f + l * 3, v);
8965 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8966 qglVertex3f(v[0], v[1], v[2]);
8967 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8968 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8969 qglVertex3f(v[0], v[1], v[2]);
8976 rsurface.texture = NULL;
8980 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8981 int r_maxsurfacelist = 0;
8982 const msurface_t **r_surfacelist = NULL;
8983 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8985 int i, j, endj, f, flagsmask;
8987 dp_model_t *model = r_refdef.scene.worldmodel;
8988 msurface_t *surfaces;
8989 unsigned char *update;
8990 int numsurfacelist = 0;
8994 if (r_maxsurfacelist < model->num_surfaces)
8996 r_maxsurfacelist = model->num_surfaces;
8998 Mem_Free((msurface_t**)r_surfacelist);
8999 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9002 RSurf_ActiveWorldEntity();
9004 surfaces = model->data_surfaces;
9005 update = model->brushq1.lightmapupdateflags;
9007 // update light styles on this submodel
9008 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9010 model_brush_lightstyleinfo_t *style;
9011 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9013 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9015 int *list = style->surfacelist;
9016 style->value = r_refdef.scene.lightstylevalue[style->style];
9017 for (j = 0;j < style->numsurfaces;j++)
9018 update[list[j]] = true;
9023 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9028 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9034 rsurface.uselightmaptexture = false;
9035 rsurface.texture = NULL;
9036 rsurface.rtlight = NULL;
9038 // add visible surfaces to draw list
9039 for (i = 0;i < model->nummodelsurfaces;i++)
9041 j = model->sortedmodelsurfaces[i];
9042 if (r_refdef.viewcache.world_surfacevisible[j])
9043 r_surfacelist[numsurfacelist++] = surfaces + j;
9045 // update lightmaps if needed
9047 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9048 if (r_refdef.viewcache.world_surfacevisible[j])
9050 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9051 // don't do anything if there were no surfaces
9052 if (!numsurfacelist)
9054 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9057 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
9058 GL_AlphaTest(false);
9060 // add to stats if desired
9061 if (r_speeds.integer && !skysurfaces && !depthonly)
9063 r_refdef.stats.world_surfaces += numsurfacelist;
9064 for (j = 0;j < numsurfacelist;j++)
9065 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9068 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9071 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
9073 int i, j, endj, f, flagsmask;
9075 dp_model_t *model = ent->model;
9076 msurface_t *surfaces;
9077 unsigned char *update;
9078 int numsurfacelist = 0;
9082 if (r_maxsurfacelist < model->num_surfaces)
9084 r_maxsurfacelist = model->num_surfaces;
9086 Mem_Free((msurface_t **)r_surfacelist);
9087 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9090 // if the model is static it doesn't matter what value we give for
9091 // wantnormals and wanttangents, so this logic uses only rules applicable
9092 // to a model, knowing that they are meaningless otherwise
9093 if (ent == r_refdef.scene.worldentity)
9094 RSurf_ActiveWorldEntity();
9095 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9096 RSurf_ActiveModelEntity(ent, false, false);
9098 RSurf_ActiveModelEntity(ent, false, false);
9100 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && vid.support.arb_fragment_shader);
9102 surfaces = model->data_surfaces;
9103 update = model->brushq1.lightmapupdateflags;
9105 // update light styles
9106 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9108 model_brush_lightstyleinfo_t *style;
9109 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9111 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9113 int *list = style->surfacelist;
9114 style->value = r_refdef.scene.lightstylevalue[style->style];
9115 for (j = 0;j < style->numsurfaces;j++)
9116 update[list[j]] = true;
9121 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9126 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9132 rsurface.uselightmaptexture = false;
9133 rsurface.texture = NULL;
9134 rsurface.rtlight = NULL;
9136 // add visible surfaces to draw list
9137 for (i = 0;i < model->nummodelsurfaces;i++)
9138 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9139 // don't do anything if there were no surfaces
9140 if (!numsurfacelist)
9142 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9145 // update lightmaps if needed
9147 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9149 R_BuildLightMap(ent, surfaces + j);
9150 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
9151 GL_AlphaTest(false);
9153 // add to stats if desired
9154 if (r_speeds.integer && !skysurfaces && !depthonly)
9156 r_refdef.stats.entities_surfaces += numsurfacelist;
9157 for (j = 0;j < numsurfacelist;j++)
9158 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9161 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9164 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
9166 static texture_t texture;
9167 static msurface_t surface;
9168 const msurface_t *surfacelist = &surface;
9170 // fake enough texture and surface state to render this geometry
9172 texture.update_lastrenderframe = -1; // regenerate this texture
9173 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9174 texture.currentskinframe = skinframe;
9175 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9176 texture.specularscalemod = 1;
9177 texture.specularpowermod = 1;
9179 surface.texture = &texture;
9180 surface.num_triangles = numtriangles;
9181 surface.num_firsttriangle = firsttriangle;
9182 surface.num_vertices = numvertices;
9183 surface.num_firstvertex = firstvertex;
9186 rsurface.texture = R_GetCurrentTexture(surface.texture);
9187 rsurface.uselightmaptexture = false;
9188 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);