2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
33 qboolean r_loadnormalmap;
42 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
43 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
44 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
45 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
46 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
47 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
48 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
49 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
51 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
52 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
53 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
54 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
55 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
57 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
59 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
60 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
61 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
62 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
63 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
64 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
65 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
66 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
67 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
68 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
69 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
71 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
72 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
73 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
74 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
75 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
76 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
77 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
78 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
79 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
80 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
81 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
82 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
83 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
84 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
85 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
86 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
87 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
88 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
89 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
90 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
91 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
92 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
93 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
94 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
95 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
96 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
97 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
99 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
102 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
103 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
104 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
105 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
106 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
107 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
108 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
110 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
111 cvar_t gl_combine = {0, "gl_combine", "1", "enables the OpenGL 1.3 rendering path"};
112 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables the OpenGL 2.0 rendering path"};
114 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)"};
115 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
116 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
117 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
118 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
119 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)"};
120 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)"};
121 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)"};
122 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)"};
124 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)"};
125 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
126 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"};
127 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
128 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
130 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
131 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
132 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
133 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
135 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
136 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
137 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
138 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
139 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
140 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
141 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
143 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
144 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
145 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
146 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)"};
148 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"};
150 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"};
152 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
154 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
155 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
156 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"};
157 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
158 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
159 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
160 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
162 extern cvar_t v_glslgamma;
164 extern qboolean v_flipped_state;
166 static struct r_bloomstate_s
171 int bloomwidth, bloomheight;
173 int screentexturewidth, screentextureheight;
174 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
176 int bloomtexturewidth, bloomtextureheight;
177 rtexture_t *texture_bloom;
179 // arrays for rendering the screen passes
180 float screentexcoord2f[8];
181 float bloomtexcoord2f[8];
182 float offsettexcoord2f[8];
184 r_viewport_t viewport;
188 r_waterstate_t r_waterstate;
190 /// shadow volume bsp struct with automatically growing nodes buffer
193 rtexture_t *r_texture_blanknormalmap;
194 rtexture_t *r_texture_white;
195 rtexture_t *r_texture_grey128;
196 rtexture_t *r_texture_black;
197 rtexture_t *r_texture_notexture;
198 rtexture_t *r_texture_whitecube;
199 rtexture_t *r_texture_normalizationcube;
200 rtexture_t *r_texture_fogattenuation;
201 rtexture_t *r_texture_gammaramps;
202 unsigned int r_texture_gammaramps_serial;
203 //rtexture_t *r_texture_fogintensity;
205 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
206 unsigned int r_numqueries;
207 unsigned int r_maxqueries;
209 typedef struct r_qwskincache_s
211 char name[MAX_QPATH];
212 skinframe_t *skinframe;
216 static r_qwskincache_t *r_qwskincache;
217 static int r_qwskincache_size;
219 /// vertex coordinates for a quad that covers the screen exactly
220 const float r_screenvertex3f[12] =
228 extern void R_DrawModelShadows(void);
230 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
233 for (i = 0;i < verts;i++)
244 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
247 for (i = 0;i < verts;i++)
257 // FIXME: move this to client?
260 if (gamemode == GAME_NEHAHRA)
262 Cvar_Set("gl_fogenable", "0");
263 Cvar_Set("gl_fogdensity", "0.2");
264 Cvar_Set("gl_fogred", "0.3");
265 Cvar_Set("gl_foggreen", "0.3");
266 Cvar_Set("gl_fogblue", "0.3");
268 r_refdef.fog_density = 0;
269 r_refdef.fog_red = 0;
270 r_refdef.fog_green = 0;
271 r_refdef.fog_blue = 0;
272 r_refdef.fog_alpha = 1;
273 r_refdef.fog_start = 0;
274 r_refdef.fog_end = 16384;
275 r_refdef.fog_height = 1<<30;
276 r_refdef.fog_fadedepth = 128;
279 static void R_BuildBlankTextures(void)
281 unsigned char data[4];
282 data[2] = 128; // normal X
283 data[1] = 128; // normal Y
284 data[0] = 255; // normal Z
285 data[3] = 128; // height
286 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
291 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
296 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
301 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
304 static void R_BuildNoTexture(void)
307 unsigned char pix[16][16][4];
308 // this makes a light grey/dark grey checkerboard texture
309 for (y = 0;y < 16;y++)
311 for (x = 0;x < 16;x++)
313 if ((y < 8) ^ (x < 8))
329 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
332 static void R_BuildWhiteCube(void)
334 unsigned char data[6*1*1*4];
335 memset(data, 255, sizeof(data));
336 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
339 static void R_BuildNormalizationCube(void)
343 vec_t s, t, intensity;
345 unsigned char data[6][NORMSIZE][NORMSIZE][4];
346 for (side = 0;side < 6;side++)
348 for (y = 0;y < NORMSIZE;y++)
350 for (x = 0;x < NORMSIZE;x++)
352 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
353 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
388 intensity = 127.0f / sqrt(DotProduct(v, v));
389 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
390 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
391 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
392 data[side][y][x][3] = 255;
396 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
399 static void R_BuildFogTexture(void)
403 unsigned char data1[FOGWIDTH][4];
404 //unsigned char data2[FOGWIDTH][4];
407 r_refdef.fogmasktable_start = r_refdef.fog_start;
408 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
409 r_refdef.fogmasktable_range = r_refdef.fogrange;
410 r_refdef.fogmasktable_density = r_refdef.fog_density;
412 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
413 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
415 d = (x * r - r_refdef.fogmasktable_start);
416 if(developer.integer >= 100)
417 Con_Printf("%f ", d);
419 if (r_fog_exp2.integer)
420 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
422 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
423 if(developer.integer >= 100)
424 Con_Printf(" : %f ", alpha);
425 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
426 if(developer.integer >= 100)
427 Con_Printf(" = %f\n", alpha);
428 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
431 for (x = 0;x < FOGWIDTH;x++)
433 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
438 //data2[x][0] = 255 - b;
439 //data2[x][1] = 255 - b;
440 //data2[x][2] = 255 - b;
443 if (r_texture_fogattenuation)
445 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
446 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
450 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
451 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
455 static const char *builtinshaderstring =
456 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
457 "// written by Forest 'LordHavoc' Hale\n"
459 "// enable various extensions depending on permutation:\n"
461 "#ifdef USESHADOWMAPRECT\n"
462 "# extension GL_ARB_texture_rectangle : enable\n"
465 "#ifdef USESHADOWMAP2D\n"
466 "# ifdef GL_EXT_gpu_shader4\n"
467 "# extension GL_EXT_gpu_shader4 : enable\n"
469 "# ifdef GL_ARB_texture_gather\n"
470 "# extension GL_ARB_texture_gather : enable\n"
472 "# ifdef GL_AMD_texture_texture4\n"
473 "# extension GL_AMD_texture_texture4 : enable\n"
478 "#ifdef USESHADOWMAPCUBE\n"
479 "# extension GL_EXT_gpu_shader4 : enable\n"
482 "#ifdef USESHADOWSAMPLER\n"
483 "# extension GL_ARB_shadow : enable\n"
486 "// common definitions between vertex shader and fragment shader:\n"
488 "//#ifdef __GLSL_CG_DATA_TYPES\n"
489 "//# define myhalf half\n"
490 "//# define myhalf2 half2\n"
491 "//# define myhalf3half3\n"
492 "//# define myhalf4 half4\n"
494 "# define myhalf float\n"
495 "# define myhalf2 vec2\n"
496 "# define myhalf3 vec3\n"
497 "# define myhalf4 vec4\n"
500 "#ifdef USEFOGINSIDE\n"
503 "# ifdef USEFOGOUTSIDE\n"
508 "#ifdef MODE_DEPTH_OR_SHADOW\n"
510 "# ifdef VERTEX_SHADER\n"
513 " gl_Position = ftransform();\n"
518 "#ifdef MODE_SHOWDEPTH\n"
519 "# ifdef VERTEX_SHADER\n"
522 " gl_Position = ftransform();\n"
523 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
526 "# ifdef FRAGMENT_SHADER\n"
529 " gl_FragColor = gl_Color;\n"
533 "#else // !MODE_SHOWDEPTH\n"
535 "#ifdef MODE_POSTPROCESS\n"
536 "# ifdef VERTEX_SHADER\n"
539 " gl_FrontColor = gl_Color;\n"
540 " gl_Position = ftransform();\n"
541 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
543 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
547 "# ifdef FRAGMENT_SHADER\n"
549 "uniform sampler2D Texture_First;\n"
551 "uniform sampler2D Texture_Second;\n"
553 "#ifdef USEGAMMARAMPS\n"
554 "uniform sampler2D Texture_GammaRamps;\n"
556 "#ifdef USESATURATION\n"
557 "uniform float Saturation;\n"
559 "#ifdef USEVIEWTINT\n"
560 "uniform vec4 TintColor;\n"
562 "//uncomment these if you want to use them:\n"
563 "uniform vec4 UserVec1;\n"
564 "// uniform vec4 UserVec2;\n"
565 "// uniform vec4 UserVec3;\n"
566 "// uniform vec4 UserVec4;\n"
567 "// uniform float ClientTime;\n"
568 "uniform vec2 PixelSize;\n"
571 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
573 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
575 "#ifdef USEVIEWTINT\n"
576 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
579 "#ifdef USEPOSTPROCESSING\n"
580 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
581 "// 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"
582 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
583 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
584 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
585 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
586 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
587 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
590 "#ifdef USESATURATION\n"
591 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
592 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
593 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
594 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
597 "#ifdef USEGAMMARAMPS\n"
598 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
599 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
600 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
607 "#ifdef MODE_GENERIC\n"
608 "# ifdef VERTEX_SHADER\n"
611 " gl_FrontColor = gl_Color;\n"
612 "# ifdef USEDIFFUSE\n"
613 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
615 "# ifdef USESPECULAR\n"
616 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
618 " gl_Position = ftransform();\n"
621 "# ifdef FRAGMENT_SHADER\n"
623 "# ifdef USEDIFFUSE\n"
624 "uniform sampler2D Texture_First;\n"
626 "# ifdef USESPECULAR\n"
627 "uniform sampler2D Texture_Second;\n"
632 " gl_FragColor = gl_Color;\n"
633 "# ifdef USEDIFFUSE\n"
634 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
637 "# ifdef USESPECULAR\n"
638 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
640 "# ifdef USECOLORMAPPING\n"
641 " gl_FragColor *= tex2;\n"
644 " gl_FragColor += tex2;\n"
646 "# ifdef USEVERTEXTEXTUREBLEND\n"
647 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
652 "#else // !MODE_GENERIC\n"
653 "#ifdef MODE_BLOOMBLUR\n"
654 "# ifdef VERTEX_SHADER\n"
657 " gl_FrontColor = gl_Color;\n"
658 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
659 " gl_Position = ftransform();\n"
662 "# ifdef FRAGMENT_SHADER\n"
664 "uniform sampler2D Texture_First;\n"
665 "uniform vec4 BloomBlur_Parameters;\n"
670 " vec2 tc = gl_TexCoord[0].xy;\n"
671 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
672 " tc += BloomBlur_Parameters.xy;\n"
673 " for (i = 1;i < SAMPLES;i++)\n"
675 " color += texture2D(Texture_First, tc).rgb;\n"
676 " tc += BloomBlur_Parameters.xy;\n"
678 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
682 "#else // !MODE_BLOOMBLUR\n"
684 "varying vec2 TexCoord;\n"
685 "#ifdef USEVERTEXTEXTUREBLEND\n"
686 "varying vec2 TexCoord2;\n"
688 "varying vec2 TexCoordLightmap;\n"
690 "#ifdef MODE_LIGHTSOURCE\n"
691 "varying vec3 CubeVector;\n"
694 "#ifdef MODE_LIGHTSOURCE\n"
695 "varying vec3 LightVector;\n"
697 "#ifdef MODE_LIGHTDIRECTION\n"
698 "varying vec3 LightVector;\n"
701 "varying vec3 EyeVector;\n"
703 "varying vec3 EyeVectorModelSpace;\n"
704 "varying float FogPlaneVertexDist;\n"
707 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
708 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
709 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
711 "#ifdef MODE_WATER\n"
712 "varying vec4 ModelViewProjectionPosition;\n"
714 "#ifdef MODE_REFRACTION\n"
715 "varying vec4 ModelViewProjectionPosition;\n"
717 "#ifdef USEREFLECTION\n"
718 "varying vec4 ModelViewProjectionPosition;\n"
725 "// vertex shader specific:\n"
726 "#ifdef VERTEX_SHADER\n"
728 "uniform vec3 LightPosition;\n"
729 "uniform vec3 EyePosition;\n"
730 "uniform vec3 LightDir;\n"
731 "uniform vec4 FogPlane;\n"
733 "// 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"
737 " gl_FrontColor = gl_Color;\n"
738 " // copy the surface texcoord\n"
739 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
740 "#ifdef USEVERTEXTEXTUREBLEND\n"
741 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
743 "#ifndef MODE_LIGHTSOURCE\n"
744 "# ifndef MODE_LIGHTDIRECTION\n"
745 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
749 "#ifdef MODE_LIGHTSOURCE\n"
750 " // transform vertex position into light attenuation/cubemap space\n"
751 " // (-1 to +1 across the light box)\n"
752 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
754 " // transform unnormalized light direction into tangent space\n"
755 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
756 " // normalize it per pixel)\n"
757 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
758 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
759 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
760 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
763 "#ifdef MODE_LIGHTDIRECTION\n"
764 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
765 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
766 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
769 " // transform unnormalized eye direction into tangent space\n"
771 " vec3 EyeVectorModelSpace;\n"
773 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
774 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
775 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
776 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
779 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
782 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
783 " VectorS = gl_MultiTexCoord1.xyz;\n"
784 " VectorT = gl_MultiTexCoord2.xyz;\n"
785 " VectorR = gl_MultiTexCoord3.xyz;\n"
788 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
789 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
790 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
791 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
794 "// transform vertex to camera space, using ftransform to match non-VS\n"
796 " gl_Position = ftransform();\n"
798 "#ifdef MODE_WATER\n"
799 " ModelViewProjectionPosition = gl_Position;\n"
801 "#ifdef MODE_REFRACTION\n"
802 " ModelViewProjectionPosition = gl_Position;\n"
804 "#ifdef USEREFLECTION\n"
805 " ModelViewProjectionPosition = gl_Position;\n"
809 "#endif // VERTEX_SHADER\n"
814 "// fragment shader specific:\n"
815 "#ifdef FRAGMENT_SHADER\n"
817 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
818 "uniform sampler2D Texture_Normal;\n"
819 "uniform sampler2D Texture_Color;\n"
820 "uniform sampler2D Texture_Gloss;\n"
821 "uniform sampler2D Texture_Glow;\n"
822 "uniform sampler2D Texture_SecondaryNormal;\n"
823 "uniform sampler2D Texture_SecondaryColor;\n"
824 "uniform sampler2D Texture_SecondaryGloss;\n"
825 "uniform sampler2D Texture_SecondaryGlow;\n"
826 "uniform sampler2D Texture_Pants;\n"
827 "uniform sampler2D Texture_Shirt;\n"
828 "uniform sampler2D Texture_FogMask;\n"
829 "uniform sampler2D Texture_Lightmap;\n"
830 "uniform sampler2D Texture_Deluxemap;\n"
831 "uniform sampler2D Texture_Refraction;\n"
832 "uniform sampler2D Texture_Reflection;\n"
833 "uniform sampler2D Texture_Attenuation;\n"
834 "uniform samplerCube Texture_Cube;\n"
836 "#define showshadowmap 0\n"
838 "#ifdef USESHADOWMAPRECT\n"
839 "# ifdef USESHADOWSAMPLER\n"
840 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
842 "uniform sampler2DRect Texture_ShadowMapRect;\n"
846 "#ifdef USESHADOWMAP2D\n"
847 "# ifdef USESHADOWSAMPLER\n"
848 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
850 "uniform sampler2D Texture_ShadowMap2D;\n"
854 "#ifdef USESHADOWMAPVSDCT\n"
855 "uniform samplerCube Texture_CubeProjection;\n"
858 "#ifdef USESHADOWMAPCUBE\n"
859 "# ifdef USESHADOWSAMPLER\n"
860 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
862 "uniform samplerCube Texture_ShadowMapCube;\n"
866 "uniform myhalf3 LightColor;\n"
867 "uniform myhalf3 AmbientColor;\n"
868 "uniform myhalf3 DiffuseColor;\n"
869 "uniform myhalf3 SpecularColor;\n"
870 "uniform myhalf3 Color_Pants;\n"
871 "uniform myhalf3 Color_Shirt;\n"
872 "uniform myhalf3 FogColor;\n"
874 "uniform myhalf4 TintColor;\n"
877 "//#ifdef MODE_WATER\n"
878 "uniform vec4 DistortScaleRefractReflect;\n"
879 "uniform vec4 ScreenScaleRefractReflect;\n"
880 "uniform vec4 ScreenCenterRefractReflect;\n"
881 "uniform myhalf4 RefractColor;\n"
882 "uniform myhalf4 ReflectColor;\n"
883 "uniform myhalf ReflectFactor;\n"
884 "uniform myhalf ReflectOffset;\n"
886 "//# ifdef MODE_REFRACTION\n"
887 "//uniform vec4 DistortScaleRefractReflect;\n"
888 "//uniform vec4 ScreenScaleRefractReflect;\n"
889 "//uniform vec4 ScreenCenterRefractReflect;\n"
890 "//uniform myhalf4 RefractColor;\n"
891 "//# ifdef USEREFLECTION\n"
892 "//uniform myhalf4 ReflectColor;\n"
895 "//# ifdef USEREFLECTION\n"
896 "//uniform vec4 DistortScaleRefractReflect;\n"
897 "//uniform vec4 ScreenScaleRefractReflect;\n"
898 "//uniform vec4 ScreenCenterRefractReflect;\n"
899 "//uniform myhalf4 ReflectColor;\n"
904 "uniform myhalf3 GlowColor;\n"
905 "uniform myhalf SceneBrightness;\n"
907 "uniform float OffsetMapping_Scale;\n"
908 "uniform float OffsetMapping_Bias;\n"
909 "uniform float FogRangeRecip;\n"
910 "uniform float FogPlaneViewDist;\n"
911 "uniform float FogHeightFade;\n"
913 "uniform myhalf AmbientScale;\n"
914 "uniform myhalf DiffuseScale;\n"
915 "uniform myhalf SpecularScale;\n"
916 "uniform myhalf SpecularPower;\n"
918 "#ifdef USEOFFSETMAPPING\n"
919 "vec2 OffsetMapping(vec2 TexCoord)\n"
921 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
922 " // 14 sample relief mapping: linear search and then binary search\n"
923 " // this basically steps forward a small amount repeatedly until it finds\n"
924 " // itself inside solid, then jitters forward and back using decreasing\n"
925 " // amounts to find the impact\n"
926 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
927 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
928 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
929 " vec3 RT = vec3(TexCoord, 1);\n"
930 " OffsetVector *= 0.1;\n"
931 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
932 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
933 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
934 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
935 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
936 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
937 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
938 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
939 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
940 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
941 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
942 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
943 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
944 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
947 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
948 " // this basically moves forward the full distance, and then backs up based\n"
949 " // on height of samples\n"
950 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
951 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
952 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
953 " TexCoord += OffsetVector;\n"
954 " OffsetVector *= 0.333;\n"
955 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
956 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
957 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
958 " return TexCoord;\n"
961 "#endif // USEOFFSETMAPPING\n"
963 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
964 "uniform vec2 ShadowMap_TextureScale;\n"
965 "uniform vec4 ShadowMap_Parameters;\n"
968 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
969 "vec3 GetShadowMapTC2D(vec3 dir)\n"
971 " vec3 adir = abs(dir);\n"
972 "# ifndef USESHADOWMAPVSDCT\n"
976 " if (adir.x > adir.y)\n"
978 " if (adir.x > adir.z) // X\n"
982 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
988 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
993 " if (adir.y > adir.z) // Y\n"
997 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1003 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1007 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1008 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1009 " stc.z += ShadowMap_Parameters.z;\n"
1010 "# if showshadowmap\n"
1011 " stc.xy *= ShadowMap_TextureScale;\n"
1015 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1016 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1017 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1018 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1019 " stc.z += ShadowMap_Parameters.z;\n"
1020 "# if showshadowmap\n"
1021 " stc.xy *= ShadowMap_TextureScale;\n"
1026 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1028 "#ifdef USESHADOWMAPCUBE\n"
1029 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1031 " vec3 adir = abs(dir);\n"
1032 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1036 "#if !showshadowmap\n"
1037 "# ifdef USESHADOWMAPRECT\n"
1038 "float ShadowMapCompare(vec3 dir)\n"
1040 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1042 "# ifdef USESHADOWSAMPLER\n"
1044 "# ifdef USESHADOWMAPPCF\n"
1045 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1046 " 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"
1048 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1053 "# ifdef USESHADOWMAPPCF\n"
1054 "# if USESHADOWMAPPCF > 1\n"
1055 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1056 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1057 " 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"
1058 " 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"
1059 " 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"
1060 " 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"
1061 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1062 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1064 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1065 " vec2 offset = fract(shadowmaptc.xy);\n"
1066 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1067 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1068 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1069 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1070 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1073 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1081 "# ifdef USESHADOWMAP2D\n"
1082 "float ShadowMapCompare(vec3 dir)\n"
1084 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1087 "# ifdef USESHADOWSAMPLER\n"
1088 "# ifdef USESHADOWMAPPCF\n"
1089 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1090 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1091 " 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"
1093 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1096 "# ifdef USESHADOWMAPPCF\n"
1097 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1098 "# ifdef GL_ARB_texture_gather\n"
1099 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1101 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1103 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1104 " center *= ShadowMap_TextureScale;\n"
1105 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1106 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1107 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1108 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1109 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1110 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1111 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1113 "# ifdef GL_EXT_gpu_shader4\n"
1114 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1116 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1118 "# if USESHADOWMAPPCF > 1\n"
1119 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1120 " center *= ShadowMap_TextureScale;\n"
1121 " 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"
1122 " 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"
1123 " 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"
1124 " 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"
1125 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1126 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1128 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1129 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1130 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1131 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1132 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1133 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1137 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1144 "# ifdef USESHADOWMAPCUBE\n"
1145 "float ShadowMapCompare(vec3 dir)\n"
1147 " // apply depth texture cubemap as light filter\n"
1148 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1150 "# ifdef USESHADOWSAMPLER\n"
1151 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1153 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1160 "#ifdef MODE_WATER\n"
1165 "#ifdef USEOFFSETMAPPING\n"
1166 " // apply offsetmapping\n"
1167 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1168 "#define TexCoord TexCoordOffset\n"
1171 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1172 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1173 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1174 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1175 " // FIXME temporary hack to detect the case that the reflection\n"
1176 " // gets blackened at edges due to leaving the area that contains actual\n"
1178 " // Remove this 'ack once we have a better way to stop this thing from\n"
1180 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1181 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1182 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1183 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1184 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1185 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1186 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1187 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1188 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1189 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1190 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1191 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1194 "#else // !MODE_WATER\n"
1195 "#ifdef MODE_REFRACTION\n"
1197 "// refraction pass\n"
1200 "#ifdef USEOFFSETMAPPING\n"
1201 " // apply offsetmapping\n"
1202 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1203 "#define TexCoord TexCoordOffset\n"
1206 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1207 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1208 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1209 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1210 " // FIXME temporary hack to detect the case that the reflection\n"
1211 " // gets blackened at edges due to leaving the area that contains actual\n"
1213 " // Remove this 'ack once we have a better way to stop this thing from\n"
1215 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1216 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1217 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1218 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1219 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1220 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1223 "#else // !MODE_REFRACTION\n"
1226 "#ifdef USEOFFSETMAPPING\n"
1227 " // apply offsetmapping\n"
1228 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1229 "#define TexCoord TexCoordOffset\n"
1232 " // combine the diffuse textures (base, pants, shirt)\n"
1233 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1234 "#ifdef USECOLORMAPPING\n"
1235 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1237 "#ifdef USEVERTEXTEXTUREBLEND\n"
1238 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1239 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1240 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1241 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1243 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1246 "#ifdef USEDIFFUSE\n"
1247 " // get the surface normal and the gloss color\n"
1248 "# ifdef USEVERTEXTEXTUREBLEND\n"
1249 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1250 "# ifdef USESPECULAR\n"
1251 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1254 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1255 "# ifdef USESPECULAR\n"
1256 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1263 "#ifdef MODE_LIGHTSOURCE\n"
1264 " // light source\n"
1266 " // calculate surface normal, light normal, and specular normal\n"
1267 " // compute color intensity for the two textures (colormap and glossmap)\n"
1268 " // scale by light color and attenuation as efficiently as possible\n"
1269 " // (do as much scalar math as possible rather than vector math)\n"
1270 "# ifdef USEDIFFUSE\n"
1271 " // get the light normal\n"
1272 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1274 "# ifdef USESPECULAR\n"
1275 "# ifndef USEEXACTSPECULARMATH\n"
1276 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1279 " // calculate directional shading\n"
1280 "# ifdef USEEXACTSPECULARMATH\n"
1281 " 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"
1283 " 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"
1286 "# ifdef USEDIFFUSE\n"
1287 " // calculate directional shading\n"
1288 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1290 " // calculate directionless shading\n"
1291 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1295 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1296 "#if !showshadowmap\n"
1297 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1301 "# ifdef USECUBEFILTER\n"
1302 " // apply light cubemap filter\n"
1303 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1304 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1306 "#endif // MODE_LIGHTSOURCE\n"
1311 "#ifdef MODE_LIGHTDIRECTION\n"
1312 " // directional model lighting\n"
1313 "# ifdef USEDIFFUSE\n"
1314 " // get the light normal\n"
1315 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1317 "# ifdef USESPECULAR\n"
1318 " // calculate directional shading\n"
1319 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1320 "# ifdef USEEXACTSPECULARMATH\n"
1321 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1323 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1324 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1327 "# ifdef USEDIFFUSE\n"
1329 " // calculate directional shading\n"
1330 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1332 " color.rgb *= AmbientColor;\n"
1335 "#endif // MODE_LIGHTDIRECTION\n"
1340 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1341 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1343 " // get the light normal\n"
1344 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1345 " myhalf3 diffusenormal;\n"
1346 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1347 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1348 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1349 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1350 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1351 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1352 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1353 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1354 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1355 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1356 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1357 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1358 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1359 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1360 "# ifdef USESPECULAR\n"
1361 "# ifdef USEEXACTSPECULARMATH\n"
1362 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1364 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1365 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1369 " // apply lightmap color\n"
1370 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1371 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1376 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1377 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1379 " // get the light normal\n"
1380 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1381 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1382 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1383 "# ifdef USESPECULAR\n"
1384 "# ifdef USEEXACTSPECULARMATH\n"
1385 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1387 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1388 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1392 " // apply lightmap color\n"
1393 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1394 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1399 "#ifdef MODE_LIGHTMAP\n"
1400 " // apply lightmap color\n"
1401 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1402 "#endif // MODE_LIGHTMAP\n"
1407 "#ifdef MODE_VERTEXCOLOR\n"
1408 " // apply lightmap color\n"
1409 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1410 "#endif // MODE_VERTEXCOLOR\n"
1415 "#ifdef MODE_FLATCOLOR\n"
1416 "#endif // MODE_FLATCOLOR\n"
1424 " color *= TintColor;\n"
1427 "#ifdef USEVERTEXTEXTUREBLEND\n"
1428 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1430 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1434 " color.rgb *= SceneBrightness;\n"
1436 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1439 "#ifdef USEFOGOUTSIDE\n"
1440 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1442 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1444 "// float FogHeightFade1 = -0.5/1024.0;\n"
1445 "// if (FogPlaneViewDist >= 0.0)\n"
1446 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade1);\n"
1448 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade1);\n"
1449 "//# ifdef USEFOGABOVE\n"
1450 "// if (FogPlaneViewDist >= 0.0)\n"
1451 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist);\n"
1453 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist));\n"
1454 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1455 "// fogfrac *= min(1.0, (max(0.0, fade*FogPlaneVertexDist) + max(0.0, fade*FogPlaneViewDist)));\n"
1456 "// fogfrac *= min(1.0, (max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1457 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1459 " //fogfrac *= min(1.0, max(0.0, (max(-2048, min(0, FogPlaneVertexDist)) + max(-2048, min(0, FogPlaneViewDist)))/-2048.0));\n"
1460 " //float fade = -0.5/128.0;\n"
1461 " //fogfrac *= max(0.0, min(1.0, fade*FogPlaneVertexDist)) + max(0.0, min(1.0, fade*FogPlaneViewDist));\n"
1462 " //fogfrac *= max(0.0, min(1.0, FogHeightFade1*FogPlaneVertexDist)) + max(0.0, min(1.0, FogHeightFade1*FogPlaneViewDist));\n"
1463 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1464 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1465 " //fogfrac *= min(1.0, min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1466 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1467 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1468 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1470 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0))));\n"
1473 " // 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"
1474 "#ifdef USEREFLECTION\n"
1475 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1476 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1477 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1478 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1479 " // FIXME temporary hack to detect the case that the reflection\n"
1480 " // gets blackened at edges due to leaving the area that contains actual\n"
1482 " // Remove this 'ack once we have a better way to stop this thing from\n"
1484 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1485 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1486 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1487 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1488 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1489 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1492 " gl_FragColor = vec4(color);\n"
1494 "#if showshadowmap\n"
1495 "# ifdef USESHADOWMAPRECT\n"
1496 "# ifdef USESHADOWSAMPLER\n"
1497 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1499 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1502 "# ifdef USESHADOWMAP2D\n"
1503 "# ifdef USESHADOWSAMPLER\n"
1504 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1506 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1510 "# ifdef USESHADOWMAPCUBE\n"
1511 "# ifdef USESHADOWSAMPLER\n"
1512 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1514 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1519 "#endif // !MODE_REFRACTION\n"
1520 "#endif // !MODE_WATER\n"
1522 "#endif // FRAGMENT_SHADER\n"
1524 "#endif // !MODE_BLOOMBLUR\n"
1525 "#endif // !MODE_GENERIC\n"
1526 "#endif // !MODE_POSTPROCESS\n"
1527 "#endif // !MODE_SHOWDEPTH\n"
1528 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1531 typedef struct shaderpermutationinfo_s
1533 const char *pretext;
1536 shaderpermutationinfo_t;
1538 typedef struct shadermodeinfo_s
1540 const char *vertexfilename;
1541 const char *geometryfilename;
1542 const char *fragmentfilename;
1543 const char *pretext;
1548 typedef enum shaderpermutation_e
1550 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1551 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1552 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1553 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1554 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1555 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1556 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1557 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1558 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1559 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1560 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1561 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1562 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1563 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1564 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1565 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1566 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1567 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1568 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1569 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1570 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1571 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1572 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1573 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1574 SHADERPERMUTATION_LIMIT = 1<<24, ///< size of permutations array
1575 SHADERPERMUTATION_COUNT = 24 ///< size of shaderpermutationinfo array
1577 shaderpermutation_t;
1579 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1580 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1582 {"#define USEDIFFUSE\n", " diffuse"},
1583 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1584 {"#define USEVIEWTINT\n", " viewtint"},
1585 {"#define USECOLORMAPPING\n", " colormapping"},
1586 {"#define USESATURATION\n", " saturation"},
1587 {"#define USEFOGINSIDE\n", " foginside"},
1588 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1589 {"#define USEGAMMARAMPS\n", " gammaramps"},
1590 {"#define USECUBEFILTER\n", " cubefilter"},
1591 {"#define USEGLOW\n", " glow"},
1592 {"#define USEBLOOM\n", " bloom"},
1593 {"#define USESPECULAR\n", " specular"},
1594 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1595 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1596 {"#define USEREFLECTION\n", " reflection"},
1597 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1598 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1599 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1600 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1601 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1602 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1603 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1604 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1605 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1608 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1609 typedef enum shadermode_e
1611 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1612 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1613 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1614 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1615 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1616 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1617 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1618 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1619 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1620 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1621 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1622 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1623 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1628 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1629 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1631 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1632 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1633 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1634 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1635 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1636 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1637 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1638 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1639 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1640 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1641 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1642 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1643 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1646 struct r_glsl_permutation_s;
1647 typedef struct r_glsl_permutation_s
1649 /// hash lookup data
1650 struct r_glsl_permutation_s *hashnext;
1652 unsigned int permutation;
1654 /// indicates if we have tried compiling this permutation already
1656 /// 0 if compilation failed
1658 /// locations of detected uniforms in program object, or -1 if not found
1659 int loc_Texture_First;
1660 int loc_Texture_Second;
1661 int loc_Texture_GammaRamps;
1662 int loc_Texture_Normal;
1663 int loc_Texture_Color;
1664 int loc_Texture_Gloss;
1665 int loc_Texture_Glow;
1666 int loc_Texture_SecondaryNormal;
1667 int loc_Texture_SecondaryColor;
1668 int loc_Texture_SecondaryGloss;
1669 int loc_Texture_SecondaryGlow;
1670 int loc_Texture_Pants;
1671 int loc_Texture_Shirt;
1672 int loc_Texture_FogMask;
1673 int loc_Texture_Lightmap;
1674 int loc_Texture_Deluxemap;
1675 int loc_Texture_Attenuation;
1676 int loc_Texture_Cube;
1677 int loc_Texture_Refraction;
1678 int loc_Texture_Reflection;
1679 int loc_Texture_ShadowMapRect;
1680 int loc_Texture_ShadowMapCube;
1681 int loc_Texture_ShadowMap2D;
1682 int loc_Texture_CubeProjection;
1684 int loc_LightPosition;
1685 int loc_EyePosition;
1686 int loc_Color_Pants;
1687 int loc_Color_Shirt;
1689 int loc_FogPlaneViewDist;
1690 int loc_FogRangeRecip;
1691 int loc_FogHeightFade;
1692 int loc_AmbientScale;
1693 int loc_DiffuseScale;
1694 int loc_SpecularScale;
1695 int loc_SpecularPower;
1697 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1698 int loc_OffsetMapping_Scale;
1700 int loc_AmbientColor;
1701 int loc_DiffuseColor;
1702 int loc_SpecularColor;
1704 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1705 int loc_GammaCoeff; ///< 1 / gamma
1706 int loc_DistortScaleRefractReflect;
1707 int loc_ScreenScaleRefractReflect;
1708 int loc_ScreenCenterRefractReflect;
1709 int loc_RefractColor;
1710 int loc_ReflectColor;
1711 int loc_ReflectFactor;
1712 int loc_ReflectOffset;
1720 int loc_ShadowMap_TextureScale;
1721 int loc_ShadowMap_Parameters;
1723 r_glsl_permutation_t;
1725 #define SHADERPERMUTATION_HASHSIZE 256
1727 /// information about each possible shader permutation
1728 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1729 /// currently selected permutation
1730 r_glsl_permutation_t *r_glsl_permutation;
1731 /// storage for permutations linked in the hash table
1732 memexpandablearray_t r_glsl_permutationarray;
1734 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1736 //unsigned int hashdepth = 0;
1737 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1738 r_glsl_permutation_t *p;
1739 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1741 if (p->mode == mode && p->permutation == permutation)
1743 //if (hashdepth > 10)
1744 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1749 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1751 p->permutation = permutation;
1752 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1753 r_glsl_permutationhash[mode][hashindex] = p;
1754 //if (hashdepth > 10)
1755 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1759 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1762 if (!filename || !filename[0])
1764 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1767 if (printfromdisknotice)
1768 Con_DPrint("from disk... ");
1769 return shaderstring;
1771 else if (!strcmp(filename, "glsl/default.glsl"))
1773 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1774 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1776 return shaderstring;
1779 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1782 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1783 int vertstrings_count = 0;
1784 int geomstrings_count = 0;
1785 int fragstrings_count = 0;
1786 char *vertexstring, *geometrystring, *fragmentstring;
1787 const char *vertstrings_list[32+3];
1788 const char *geomstrings_list[32+3];
1789 const char *fragstrings_list[32+3];
1790 char permutationname[256];
1797 permutationname[0] = 0;
1798 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1799 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1800 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1802 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1804 // the first pretext is which type of shader to compile as
1805 // (later these will all be bound together as a program object)
1806 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1807 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1808 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1810 // the second pretext is the mode (for example a light source)
1811 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1812 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1813 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1814 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1816 // now add all the permutation pretexts
1817 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1819 if (permutation & (1<<i))
1821 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1822 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1823 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1824 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1828 // keep line numbers correct
1829 vertstrings_list[vertstrings_count++] = "\n";
1830 geomstrings_list[geomstrings_count++] = "\n";
1831 fragstrings_list[fragstrings_count++] = "\n";
1835 // now append the shader text itself
1836 vertstrings_list[vertstrings_count++] = vertexstring;
1837 geomstrings_list[geomstrings_count++] = geometrystring;
1838 fragstrings_list[fragstrings_count++] = fragmentstring;
1840 // if any sources were NULL, clear the respective list
1842 vertstrings_count = 0;
1843 if (!geometrystring)
1844 geomstrings_count = 0;
1845 if (!fragmentstring)
1846 fragstrings_count = 0;
1848 // compile the shader program
1849 if (vertstrings_count + geomstrings_count + fragstrings_count)
1850 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1854 qglUseProgramObjectARB(p->program);CHECKGLERROR
1855 // look up all the uniform variable names we care about, so we don't
1856 // have to look them up every time we set them
1857 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1858 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1859 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1860 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1861 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1862 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1863 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1864 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1865 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1866 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1867 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1868 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1869 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1870 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1871 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1872 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1873 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1874 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1875 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1876 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1877 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1878 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1879 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1880 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1881 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1882 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1883 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1884 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1885 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1886 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
1887 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
1888 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1889 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
1890 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1891 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1892 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1893 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1894 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1895 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1896 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1897 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1898 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1899 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1900 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1901 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1902 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1903 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1904 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1905 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1906 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1907 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1908 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1909 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1910 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1911 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1912 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1913 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1914 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1915 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1916 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1917 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1918 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1919 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1920 // initialize the samplers to refer to the texture units we use
1921 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1922 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1923 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1924 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1925 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1926 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1927 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1928 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1929 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1930 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1931 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1932 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1933 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1934 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1935 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1936 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1937 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1938 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1939 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1940 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1941 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1942 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1943 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1944 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1946 if (developer.integer)
1947 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1950 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1954 Mem_Free(vertexstring);
1956 Mem_Free(geometrystring);
1958 Mem_Free(fragmentstring);
1961 void R_GLSL_Restart_f(void)
1963 unsigned int i, limit;
1964 r_glsl_permutation_t *p;
1965 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1966 for (i = 0;i < limit;i++)
1968 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1970 GL_Backend_FreeProgram(p->program);
1971 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1974 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1977 void R_GLSL_DumpShader_f(void)
1981 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1984 Con_Printf("failed to write to glsl/default.glsl\n");
1988 FS_Print(file, "/* The engine may define the following macros:\n");
1989 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1990 for (i = 0;i < SHADERMODE_COUNT;i++)
1991 FS_Print(file, shadermodeinfo[i].pretext);
1992 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1993 FS_Print(file, shaderpermutationinfo[i].pretext);
1994 FS_Print(file, "*/\n");
1995 FS_Print(file, builtinshaderstring);
1998 Con_Printf("glsl/default.glsl written\n");
2001 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
2003 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2004 if (r_glsl_permutation != perm)
2006 r_glsl_permutation = perm;
2007 if (!r_glsl_permutation->program)
2009 if (!r_glsl_permutation->compiled)
2010 R_GLSL_CompilePermutation(perm, mode, permutation);
2011 if (!r_glsl_permutation->program)
2013 // remove features until we find a valid permutation
2015 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2017 // reduce i more quickly whenever it would not remove any bits
2018 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2019 if (!(permutation & j))
2022 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2023 if (!r_glsl_permutation->compiled)
2024 R_GLSL_CompilePermutation(perm, mode, permutation);
2025 if (r_glsl_permutation->program)
2028 if (i >= SHADERPERMUTATION_COUNT)
2030 Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2031 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2032 qglUseProgramObjectARB(0);CHECKGLERROR
2033 return; // no bit left to clear, entire mode is broken
2038 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2042 void R_SetupGenericShader(qboolean usetexture)
2044 if (vid.support.arb_fragment_shader)
2047 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2048 else if (r_glsl_permutation)
2050 r_glsl_permutation = NULL;
2051 qglUseProgramObjectARB(0);CHECKGLERROR
2056 void R_SetupGenericTwoTextureShader(int texturemode)
2058 if (vid.support.arb_fragment_shader)
2061 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))));
2062 else if (r_glsl_permutation)
2064 r_glsl_permutation = NULL;
2065 qglUseProgramObjectARB(0);CHECKGLERROR
2068 if (!r_glsl_permutation)
2069 R_Mesh_TexCombine(1, GL_DECAL, GL_DECAL, 1, 1);
2072 void R_SetupDepthOrShadowShader(void)
2074 if (vid.support.arb_fragment_shader)
2077 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2078 else if (r_glsl_permutation)
2080 r_glsl_permutation = NULL;
2081 qglUseProgramObjectARB(0);CHECKGLERROR
2086 void R_SetupShowDepthShader(void)
2088 if (vid.support.arb_fragment_shader)
2091 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2092 else if (r_glsl_permutation)
2094 r_glsl_permutation = NULL;
2095 qglUseProgramObjectARB(0);CHECKGLERROR
2100 extern rtexture_t *r_shadow_attenuationgradienttexture;
2101 extern rtexture_t *r_shadow_attenuation2dtexture;
2102 extern rtexture_t *r_shadow_attenuation3dtexture;
2103 extern qboolean r_shadow_usingshadowmaprect;
2104 extern qboolean r_shadow_usingshadowmapcube;
2105 extern qboolean r_shadow_usingshadowmap2d;
2106 extern float r_shadow_shadowmap_texturescale[2];
2107 extern float r_shadow_shadowmap_parameters[4];
2108 extern qboolean r_shadow_shadowmapvsdct;
2109 extern qboolean r_shadow_shadowmapsampler;
2110 extern int r_shadow_shadowmappcf;
2111 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2113 // select a permutation of the lighting shader appropriate to this
2114 // combination of texture, entity, light source, and fogging, only use the
2115 // minimum features necessary to avoid wasting rendering time in the
2116 // fragment shader on features that are not being used
2117 unsigned int permutation = 0;
2118 unsigned int mode = 0;
2119 // TODO: implement geometry-shader based shadow volumes someday
2120 if (r_glsl_offsetmapping.integer)
2122 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2123 if (r_glsl_offsetmapping_reliefmapping.integer)
2124 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2126 if (rsurfacepass == RSURFPASS_BACKGROUND)
2128 // distorted background
2129 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2130 mode = SHADERMODE_WATER;
2132 mode = SHADERMODE_REFRACTION;
2134 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2137 mode = SHADERMODE_LIGHTSOURCE;
2138 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2139 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2140 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2141 permutation |= SHADERPERMUTATION_CUBEFILTER;
2142 if (diffusescale > 0)
2143 permutation |= SHADERPERMUTATION_DIFFUSE;
2144 if (specularscale > 0)
2145 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2146 if (r_refdef.fogenabled)
2147 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2148 if (rsurface.texture->colormapping)
2149 permutation |= SHADERPERMUTATION_COLORMAPPING;
2150 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2152 if (r_shadow_usingshadowmaprect)
2153 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2154 if (r_shadow_usingshadowmap2d)
2155 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2156 if (r_shadow_usingshadowmapcube)
2157 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2158 else if(r_shadow_shadowmapvsdct)
2159 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2161 if (r_shadow_shadowmapsampler)
2162 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2163 if (r_shadow_shadowmappcf > 1)
2164 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2165 else if (r_shadow_shadowmappcf)
2166 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2169 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2171 // unshaded geometry (fullbright or ambient model lighting)
2172 mode = SHADERMODE_FLATCOLOR;
2173 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2174 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2175 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2176 permutation |= SHADERPERMUTATION_GLOW;
2177 if (r_refdef.fogenabled)
2178 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2179 if (rsurface.texture->colormapping)
2180 permutation |= SHADERPERMUTATION_COLORMAPPING;
2181 if (r_glsl_offsetmapping.integer)
2183 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2184 if (r_glsl_offsetmapping_reliefmapping.integer)
2185 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2187 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2188 permutation |= SHADERPERMUTATION_REFLECTION;
2190 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2192 // directional model lighting
2193 mode = SHADERMODE_LIGHTDIRECTION;
2194 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2195 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2196 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2197 permutation |= SHADERPERMUTATION_GLOW;
2198 permutation |= SHADERPERMUTATION_DIFFUSE;
2199 if (specularscale > 0)
2200 permutation |= SHADERPERMUTATION_SPECULAR;
2201 if (r_refdef.fogenabled)
2202 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2203 if (rsurface.texture->colormapping)
2204 permutation |= SHADERPERMUTATION_COLORMAPPING;
2205 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2206 permutation |= SHADERPERMUTATION_REFLECTION;
2208 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2210 // ambient model lighting
2211 mode = SHADERMODE_LIGHTDIRECTION;
2212 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2213 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2214 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2215 permutation |= SHADERPERMUTATION_GLOW;
2216 if (r_refdef.fogenabled)
2217 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2218 if (rsurface.texture->colormapping)
2219 permutation |= SHADERPERMUTATION_COLORMAPPING;
2220 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2221 permutation |= SHADERPERMUTATION_REFLECTION;
2226 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2228 // deluxemapping (light direction texture)
2229 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2230 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2232 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2233 permutation |= SHADERPERMUTATION_DIFFUSE;
2234 if (specularscale > 0)
2235 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2237 else if (r_glsl_deluxemapping.integer >= 2)
2239 // fake deluxemapping (uniform light direction in tangentspace)
2240 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2241 permutation |= SHADERPERMUTATION_DIFFUSE;
2242 if (specularscale > 0)
2243 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2245 else if (rsurface.uselightmaptexture)
2247 // ordinary lightmapping (q1bsp, q3bsp)
2248 mode = SHADERMODE_LIGHTMAP;
2252 // ordinary vertex coloring (q3bsp)
2253 mode = SHADERMODE_VERTEXCOLOR;
2255 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2256 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2257 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258 permutation |= SHADERPERMUTATION_GLOW;
2259 if (r_refdef.fogenabled)
2260 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2261 if (rsurface.texture->colormapping)
2262 permutation |= SHADERPERMUTATION_COLORMAPPING;
2263 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2264 permutation |= SHADERPERMUTATION_REFLECTION;
2266 if(permutation & SHADERPERMUTATION_SPECULAR)
2267 if(r_shadow_glossexact.integer)
2268 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2269 R_SetupShader_SetPermutation(mode, permutation);
2270 if (mode == SHADERMODE_LIGHTSOURCE)
2272 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2273 if (permutation & SHADERPERMUTATION_DIFFUSE)
2275 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2276 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2277 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2278 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2282 // ambient only is simpler
2283 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
2284 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2285 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2286 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2288 // additive passes are only darkened by fog, not tinted
2289 if (r_glsl_permutation->loc_FogColor >= 0)
2290 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2291 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2292 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2296 if (mode == SHADERMODE_LIGHTDIRECTION)
2298 if (r_glsl_permutation->loc_AmbientColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale * 0.5f, rsurface.modellight_ambient[1] * ambientscale * 0.5f, rsurface.modellight_ambient[2] * ambientscale * 0.5f);
2299 if (r_glsl_permutation->loc_DiffuseColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale * 0.5f, rsurface.modellight_diffuse[1] * diffusescale * 0.5f, rsurface.modellight_diffuse[2] * diffusescale * 0.5f);
2300 if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
2301 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2305 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2306 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2307 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2309 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
2310 if (r_glsl_permutation->loc_GlowColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_GlowColor, rsurface.glowmod[0] * r_hdr_glowintensity.value, rsurface.glowmod[1] * r_hdr_glowintensity.value, rsurface.glowmod[2] * r_hdr_glowintensity.value);
2311 // additive passes are only darkened by fog, not tinted
2312 if (r_glsl_permutation->loc_FogColor >= 0)
2314 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2315 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2317 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2319 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2320 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2321 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2322 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2323 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2324 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2325 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2327 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2328 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2329 if (r_glsl_permutation->loc_Color_Pants >= 0)
2331 if (rsurface.texture->currentskinframe->pants)
2332 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2334 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2336 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2338 if (rsurface.texture->currentskinframe->shirt)
2339 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2341 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2343 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2344 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2345 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2346 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2347 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2349 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2353 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2355 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2359 #define SKINFRAME_HASH 1024
2363 int loadsequence; // incremented each level change
2364 memexpandablearray_t array;
2365 skinframe_t *hash[SKINFRAME_HASH];
2368 r_skinframe_t r_skinframe;
2370 void R_SkinFrame_PrepareForPurge(void)
2372 r_skinframe.loadsequence++;
2373 // wrap it without hitting zero
2374 if (r_skinframe.loadsequence >= 200)
2375 r_skinframe.loadsequence = 1;
2378 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2382 // mark the skinframe as used for the purging code
2383 skinframe->loadsequence = r_skinframe.loadsequence;
2386 void R_SkinFrame_Purge(void)
2390 for (i = 0;i < SKINFRAME_HASH;i++)
2392 for (s = r_skinframe.hash[i];s;s = s->next)
2394 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2396 if (s->merged == s->base)
2398 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2399 R_PurgeTexture(s->stain );s->stain = NULL;
2400 R_PurgeTexture(s->merged);s->merged = NULL;
2401 R_PurgeTexture(s->base );s->base = NULL;
2402 R_PurgeTexture(s->pants );s->pants = NULL;
2403 R_PurgeTexture(s->shirt );s->shirt = NULL;
2404 R_PurgeTexture(s->nmap );s->nmap = NULL;
2405 R_PurgeTexture(s->gloss );s->gloss = NULL;
2406 R_PurgeTexture(s->glow );s->glow = NULL;
2407 R_PurgeTexture(s->fog );s->fog = NULL;
2408 s->loadsequence = 0;
2414 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2416 char basename[MAX_QPATH];
2418 Image_StripImageExtension(name, basename, sizeof(basename));
2420 if( last == NULL ) {
2422 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2423 item = r_skinframe.hash[hashindex];
2428 // linearly search through the hash bucket
2429 for( ; item ; item = item->next ) {
2430 if( !strcmp( item->basename, basename ) ) {
2437 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2441 char basename[MAX_QPATH];
2443 Image_StripImageExtension(name, basename, sizeof(basename));
2445 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2446 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2447 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2451 rtexture_t *dyntexture;
2452 // check whether its a dynamic texture
2453 dyntexture = CL_GetDynTexture( basename );
2454 if (!add && !dyntexture)
2456 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2457 memset(item, 0, sizeof(*item));
2458 strlcpy(item->basename, basename, sizeof(item->basename));
2459 item->base = dyntexture; // either NULL or dyntexture handle
2460 item->textureflags = textureflags;
2461 item->comparewidth = comparewidth;
2462 item->compareheight = compareheight;
2463 item->comparecrc = comparecrc;
2464 item->next = r_skinframe.hash[hashindex];
2465 r_skinframe.hash[hashindex] = item;
2467 else if( item->base == NULL )
2469 rtexture_t *dyntexture;
2470 // check whether its a dynamic texture
2471 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
2472 dyntexture = CL_GetDynTexture( basename );
2473 item->base = dyntexture; // either NULL or dyntexture handle
2476 R_SkinFrame_MarkUsed(item);
2480 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2482 unsigned long long avgcolor[5], wsum; \
2490 for(pix = 0; pix < cnt; ++pix) \
2493 for(comp = 0; comp < 3; ++comp) \
2495 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2498 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2500 for(comp = 0; comp < 3; ++comp) \
2501 avgcolor[comp] += getpixel * w; \
2504 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2505 avgcolor[4] += getpixel; \
2507 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2509 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2510 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2511 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2512 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2515 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2518 unsigned char *pixels;
2519 unsigned char *bumppixels;
2520 unsigned char *basepixels = NULL;
2521 int basepixels_width;
2522 int basepixels_height;
2523 skinframe_t *skinframe;
2525 if (cls.state == ca_dedicated)
2528 // return an existing skinframe if already loaded
2529 // if loading of the first image fails, don't make a new skinframe as it
2530 // would cause all future lookups of this to be missing
2531 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2532 if (skinframe && skinframe->base)
2535 basepixels = loadimagepixelsbgra(name, complain, true);
2536 if (basepixels == NULL)
2539 if (developer_loading.integer)
2540 Con_Printf("loading skin \"%s\"\n", name);
2542 // we've got some pixels to store, so really allocate this new texture now
2544 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2545 skinframe->stain = NULL;
2546 skinframe->merged = NULL;
2547 skinframe->base = r_texture_notexture;
2548 skinframe->pants = NULL;
2549 skinframe->shirt = NULL;
2550 skinframe->nmap = r_texture_blanknormalmap;
2551 skinframe->gloss = NULL;
2552 skinframe->glow = NULL;
2553 skinframe->fog = NULL;
2554 skinframe->hasalpha = false;
2556 basepixels_width = image_width;
2557 basepixels_height = image_height;
2558 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);
2560 if (textureflags & TEXF_ALPHA)
2562 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2564 if (basepixels[j] < 255)
2566 skinframe->hasalpha = true;
2570 if (r_loadfog && skinframe->hasalpha)
2572 // has transparent pixels
2573 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2574 for (j = 0;j < image_width * image_height * 4;j += 4)
2579 pixels[j+3] = basepixels[j+3];
2581 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);
2586 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2587 //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]);
2589 // _norm is the name used by tenebrae and has been adopted as standard
2590 if (r_loadnormalmap)
2592 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2594 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);
2598 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2600 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2601 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2602 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2604 Mem_Free(bumppixels);
2606 else if (r_shadow_bumpscale_basetexture.value > 0)
2608 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2609 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2610 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);
2614 // _luma is supported for tenebrae compatibility
2615 // (I think it's a very stupid name, but oh well)
2616 // _glow is the preferred name
2617 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;}
2618 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;}
2619 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;}
2620 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;}
2623 Mem_Free(basepixels);
2628 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2629 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2632 unsigned char *temp1, *temp2;
2633 skinframe_t *skinframe;
2635 if (cls.state == ca_dedicated)
2638 // if already loaded just return it, otherwise make a new skinframe
2639 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2640 if (skinframe && skinframe->base)
2643 skinframe->stain = NULL;
2644 skinframe->merged = NULL;
2645 skinframe->base = r_texture_notexture;
2646 skinframe->pants = NULL;
2647 skinframe->shirt = NULL;
2648 skinframe->nmap = r_texture_blanknormalmap;
2649 skinframe->gloss = NULL;
2650 skinframe->glow = NULL;
2651 skinframe->fog = NULL;
2652 skinframe->hasalpha = false;
2654 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2658 if (developer_loading.integer)
2659 Con_Printf("loading 32bit skin \"%s\"\n", name);
2661 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2663 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2664 temp2 = temp1 + width * height * 4;
2665 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2666 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2669 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2670 if (textureflags & TEXF_ALPHA)
2672 for (i = 3;i < width * height * 4;i += 4)
2674 if (skindata[i] < 255)
2676 skinframe->hasalpha = true;
2680 if (r_loadfog && skinframe->hasalpha)
2682 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2683 memcpy(fogpixels, skindata, width * height * 4);
2684 for (i = 0;i < width * height * 4;i += 4)
2685 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2686 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2687 Mem_Free(fogpixels);
2691 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2692 //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]);
2697 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2701 skinframe_t *skinframe;
2703 if (cls.state == ca_dedicated)
2706 // if already loaded just return it, otherwise make a new skinframe
2707 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2708 if (skinframe && skinframe->base)
2711 skinframe->stain = NULL;
2712 skinframe->merged = NULL;
2713 skinframe->base = r_texture_notexture;
2714 skinframe->pants = NULL;
2715 skinframe->shirt = NULL;
2716 skinframe->nmap = r_texture_blanknormalmap;
2717 skinframe->gloss = NULL;
2718 skinframe->glow = NULL;
2719 skinframe->fog = NULL;
2720 skinframe->hasalpha = false;
2722 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2726 if (developer_loading.integer)
2727 Con_Printf("loading quake skin \"%s\"\n", name);
2729 // 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)
2730 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
2731 memcpy(skinframe->qpixels, skindata, width*height);
2732 skinframe->qwidth = width;
2733 skinframe->qheight = height;
2736 for (i = 0;i < width * height;i++)
2737 featuresmask |= palette_featureflags[skindata[i]];
2739 skinframe->hasalpha = false;
2740 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2741 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2742 skinframe->qgeneratemerged = true;
2743 skinframe->qgeneratebase = skinframe->qhascolormapping;
2744 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2746 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2747 //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]);
2752 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2756 unsigned char *skindata;
2758 if (!skinframe->qpixels)
2761 if (!skinframe->qhascolormapping)
2762 colormapped = false;
2766 if (!skinframe->qgeneratebase)
2771 if (!skinframe->qgeneratemerged)
2775 width = skinframe->qwidth;
2776 height = skinframe->qheight;
2777 skindata = skinframe->qpixels;
2779 if (skinframe->qgeneratenmap)
2781 unsigned char *temp1, *temp2;
2782 skinframe->qgeneratenmap = false;
2783 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2784 temp2 = temp1 + width * height * 4;
2785 // use either a custom palette or the quake palette
2786 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2787 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2788 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2792 if (skinframe->qgenerateglow)
2794 skinframe->qgenerateglow = false;
2795 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
2800 skinframe->qgeneratebase = false;
2801 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);
2802 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
2803 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
2807 skinframe->qgeneratemerged = false;
2808 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
2811 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
2813 Mem_Free(skinframe->qpixels);
2814 skinframe->qpixels = NULL;
2818 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)
2821 skinframe_t *skinframe;
2823 if (cls.state == ca_dedicated)
2826 // if already loaded just return it, otherwise make a new skinframe
2827 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2828 if (skinframe && skinframe->base)
2831 skinframe->stain = NULL;
2832 skinframe->merged = NULL;
2833 skinframe->base = r_texture_notexture;
2834 skinframe->pants = NULL;
2835 skinframe->shirt = NULL;
2836 skinframe->nmap = r_texture_blanknormalmap;
2837 skinframe->gloss = NULL;
2838 skinframe->glow = NULL;
2839 skinframe->fog = NULL;
2840 skinframe->hasalpha = false;
2842 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2846 if (developer_loading.integer)
2847 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2849 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
2850 if (textureflags & TEXF_ALPHA)
2852 for (i = 0;i < width * height;i++)
2854 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
2856 skinframe->hasalpha = true;
2860 if (r_loadfog && skinframe->hasalpha)
2861 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
2864 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2865 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2870 skinframe_t *R_SkinFrame_LoadMissing(void)
2872 skinframe_t *skinframe;
2874 if (cls.state == ca_dedicated)
2877 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2878 skinframe->stain = NULL;
2879 skinframe->merged = NULL;
2880 skinframe->base = r_texture_notexture;
2881 skinframe->pants = NULL;
2882 skinframe->shirt = NULL;
2883 skinframe->nmap = r_texture_blanknormalmap;
2884 skinframe->gloss = NULL;
2885 skinframe->glow = NULL;
2886 skinframe->fog = NULL;
2887 skinframe->hasalpha = false;
2889 skinframe->avgcolor[0] = rand() / RAND_MAX;
2890 skinframe->avgcolor[1] = rand() / RAND_MAX;
2891 skinframe->avgcolor[2] = rand() / RAND_MAX;
2892 skinframe->avgcolor[3] = 1;
2897 void R_Main_FreeViewCache(void)
2899 if (r_refdef.viewcache.entityvisible)
2900 Mem_Free(r_refdef.viewcache.entityvisible);
2901 if (r_refdef.viewcache.world_pvsbits)
2902 Mem_Free(r_refdef.viewcache.world_pvsbits);
2903 if (r_refdef.viewcache.world_leafvisible)
2904 Mem_Free(r_refdef.viewcache.world_leafvisible);
2905 if (r_refdef.viewcache.world_surfacevisible)
2906 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2907 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2910 void R_Main_ResizeViewCache(void)
2912 int numentities = r_refdef.scene.numentities;
2913 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
2914 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
2915 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
2916 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
2917 if (r_refdef.viewcache.maxentities < numentities)
2919 r_refdef.viewcache.maxentities = numentities;
2920 if (r_refdef.viewcache.entityvisible)
2921 Mem_Free(r_refdef.viewcache.entityvisible);
2922 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
2924 if (r_refdef.viewcache.world_numclusters != numclusters)
2926 r_refdef.viewcache.world_numclusters = numclusters;
2927 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
2928 if (r_refdef.viewcache.world_pvsbits)
2929 Mem_Free(r_refdef.viewcache.world_pvsbits);
2930 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
2932 if (r_refdef.viewcache.world_numleafs != numleafs)
2934 r_refdef.viewcache.world_numleafs = numleafs;
2935 if (r_refdef.viewcache.world_leafvisible)
2936 Mem_Free(r_refdef.viewcache.world_leafvisible);
2937 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
2939 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
2941 r_refdef.viewcache.world_numsurfaces = numsurfaces;
2942 if (r_refdef.viewcache.world_surfacevisible)
2943 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2944 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
2948 void gl_main_start(void)
2950 r_loadnormalmap = r_loadgloss = vid.support.arb_texture_env_dot3 || vid.support.arb_fragment_shader;
2955 memset(r_queries, 0, sizeof(r_queries));
2957 r_qwskincache = NULL;
2958 r_qwskincache_size = 0;
2960 // set up r_skinframe loading system for textures
2961 memset(&r_skinframe, 0, sizeof(r_skinframe));
2962 r_skinframe.loadsequence = 1;
2963 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2965 r_main_texturepool = R_AllocTexturePool();
2966 R_BuildBlankTextures();
2968 if (vid.support.arb_texture_cube_map)
2971 R_BuildNormalizationCube();
2973 r_texture_fogattenuation = NULL;
2974 r_texture_gammaramps = NULL;
2975 //r_texture_fogintensity = NULL;
2976 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2977 memset(&r_waterstate, 0, sizeof(r_waterstate));
2978 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2979 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2980 memset(&r_svbsp, 0, sizeof (r_svbsp));
2982 r_refdef.fogmasktable_density = 0;
2985 extern rtexture_t *loadingscreentexture;
2986 void gl_main_shutdown(void)
2988 R_Main_FreeViewCache();
2991 qglDeleteQueriesARB(r_maxqueries, r_queries);
2995 memset(r_queries, 0, sizeof(r_queries));
2997 r_qwskincache = NULL;
2998 r_qwskincache_size = 0;
3000 // clear out the r_skinframe state
3001 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3002 memset(&r_skinframe, 0, sizeof(r_skinframe));
3005 Mem_Free(r_svbsp.nodes);
3006 memset(&r_svbsp, 0, sizeof (r_svbsp));
3007 R_FreeTexturePool(&r_main_texturepool);
3008 loadingscreentexture = NULL;
3009 r_texture_blanknormalmap = NULL;
3010 r_texture_white = NULL;
3011 r_texture_grey128 = NULL;
3012 r_texture_black = NULL;
3013 r_texture_whitecube = NULL;
3014 r_texture_normalizationcube = NULL;
3015 r_texture_fogattenuation = NULL;
3016 r_texture_gammaramps = NULL;
3017 //r_texture_fogintensity = NULL;
3018 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3019 memset(&r_waterstate, 0, sizeof(r_waterstate));
3023 extern void CL_ParseEntityLump(char *entitystring);
3024 void gl_main_newmap(void)
3026 // FIXME: move this code to client
3028 char *entities, entname[MAX_QPATH];
3030 Mem_Free(r_qwskincache);
3031 r_qwskincache = NULL;
3032 r_qwskincache_size = 0;
3035 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
3036 l = (int)strlen(entname) - 4;
3037 if (l >= 0 && !strcmp(entname + l, ".bsp"))
3039 memcpy(entname + l, ".ent", 5);
3040 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3042 CL_ParseEntityLump(entities);
3047 if (cl.worldmodel->brush.entities)
3048 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3050 R_Main_FreeViewCache();
3053 void GL_Main_Init(void)
3055 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3057 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3058 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3059 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3060 if (gamemode == GAME_NEHAHRA)
3062 Cvar_RegisterVariable (&gl_fogenable);
3063 Cvar_RegisterVariable (&gl_fogdensity);
3064 Cvar_RegisterVariable (&gl_fogred);
3065 Cvar_RegisterVariable (&gl_foggreen);
3066 Cvar_RegisterVariable (&gl_fogblue);
3067 Cvar_RegisterVariable (&gl_fogstart);
3068 Cvar_RegisterVariable (&gl_fogend);
3069 Cvar_RegisterVariable (&gl_skyclip);
3071 Cvar_RegisterVariable(&r_motionblur);
3072 Cvar_RegisterVariable(&r_motionblur_maxblur);
3073 Cvar_RegisterVariable(&r_motionblur_bmin);
3074 Cvar_RegisterVariable(&r_motionblur_vmin);
3075 Cvar_RegisterVariable(&r_motionblur_vmax);
3076 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3077 Cvar_RegisterVariable(&r_motionblur_randomize);
3078 Cvar_RegisterVariable(&r_damageblur);
3079 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3080 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3081 Cvar_RegisterVariable(&r_equalize_entities_by);
3082 Cvar_RegisterVariable(&r_equalize_entities_to);
3083 Cvar_RegisterVariable(&r_animcache);
3084 Cvar_RegisterVariable(&r_depthfirst);
3085 Cvar_RegisterVariable(&r_useinfinitefarclip);
3086 Cvar_RegisterVariable(&r_farclip_base);
3087 Cvar_RegisterVariable(&r_farclip_world);
3088 Cvar_RegisterVariable(&r_nearclip);
3089 Cvar_RegisterVariable(&r_showbboxes);
3090 Cvar_RegisterVariable(&r_showsurfaces);
3091 Cvar_RegisterVariable(&r_showtris);
3092 Cvar_RegisterVariable(&r_shownormals);
3093 Cvar_RegisterVariable(&r_showlighting);
3094 Cvar_RegisterVariable(&r_showshadowvolumes);
3095 Cvar_RegisterVariable(&r_showcollisionbrushes);
3096 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3097 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3098 Cvar_RegisterVariable(&r_showdisabledepthtest);
3099 Cvar_RegisterVariable(&r_drawportals);
3100 Cvar_RegisterVariable(&r_drawentities);
3101 Cvar_RegisterVariable(&r_cullentities_trace);
3102 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3103 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3104 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3105 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3106 Cvar_RegisterVariable(&r_drawviewmodel);
3107 Cvar_RegisterVariable(&r_speeds);
3108 Cvar_RegisterVariable(&r_fullbrights);
3109 Cvar_RegisterVariable(&r_wateralpha);
3110 Cvar_RegisterVariable(&r_dynamic);
3111 Cvar_RegisterVariable(&r_fullbright);
3112 Cvar_RegisterVariable(&r_shadows);
3113 Cvar_RegisterVariable(&r_shadows_darken);
3114 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3115 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3116 Cvar_RegisterVariable(&r_shadows_throwdistance);
3117 Cvar_RegisterVariable(&r_shadows_throwdirection);
3118 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3119 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3120 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3121 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3122 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3123 Cvar_RegisterVariable(&r_fog_exp2);
3124 Cvar_RegisterVariable(&r_drawfog);
3125 Cvar_RegisterVariable(&r_textureunits);
3126 Cvar_RegisterVariable(&gl_combine);
3127 Cvar_RegisterVariable(&r_glsl);
3128 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3129 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3130 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3131 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3132 Cvar_RegisterVariable(&r_glsl_postprocess);
3133 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3134 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3135 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3136 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3137 Cvar_RegisterVariable(&r_water);
3138 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3139 Cvar_RegisterVariable(&r_water_clippingplanebias);
3140 Cvar_RegisterVariable(&r_water_refractdistort);
3141 Cvar_RegisterVariable(&r_water_reflectdistort);
3142 Cvar_RegisterVariable(&r_lerpsprites);
3143 Cvar_RegisterVariable(&r_lerpmodels);
3144 Cvar_RegisterVariable(&r_lerplightstyles);
3145 Cvar_RegisterVariable(&r_waterscroll);
3146 Cvar_RegisterVariable(&r_bloom);
3147 Cvar_RegisterVariable(&r_bloom_colorscale);
3148 Cvar_RegisterVariable(&r_bloom_brighten);
3149 Cvar_RegisterVariable(&r_bloom_blur);
3150 Cvar_RegisterVariable(&r_bloom_resolution);
3151 Cvar_RegisterVariable(&r_bloom_colorexponent);
3152 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3153 Cvar_RegisterVariable(&r_hdr);
3154 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3155 Cvar_RegisterVariable(&r_hdr_glowintensity);
3156 Cvar_RegisterVariable(&r_hdr_range);
3157 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3158 Cvar_RegisterVariable(&developer_texturelogging);
3159 Cvar_RegisterVariable(&gl_lightmaps);
3160 Cvar_RegisterVariable(&r_test);
3161 Cvar_RegisterVariable(&r_batchmode);
3162 Cvar_RegisterVariable(&r_glsl_saturation);
3163 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3164 Cvar_SetValue("r_fullbrights", 0);
3165 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3167 Cvar_RegisterVariable(&r_track_sprites);
3168 Cvar_RegisterVariable(&r_track_sprites_flags);
3169 Cvar_RegisterVariable(&r_track_sprites_scalew);
3170 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3173 extern void R_Textures_Init(void);
3174 extern void GL_Draw_Init(void);
3175 extern void GL_Main_Init(void);
3176 extern void R_Shadow_Init(void);
3177 extern void R_Sky_Init(void);
3178 extern void GL_Surf_Init(void);
3179 extern void R_Particles_Init(void);
3180 extern void R_Explosion_Init(void);
3181 extern void gl_backend_init(void);
3182 extern void Sbar_Init(void);
3183 extern void R_LightningBeams_Init(void);
3184 extern void Mod_RenderInit(void);
3186 void Render_Init(void)
3198 R_LightningBeams_Init();
3207 extern char *ENGINE_EXTENSIONS;
3210 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3211 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3212 gl_version = (const char *)qglGetString(GL_VERSION);
3213 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3217 if (!gl_platformextensions)
3218 gl_platformextensions = "";
3220 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3221 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3222 Con_Printf("GL_VERSION: %s\n", gl_version);
3223 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3224 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3226 VID_CheckExtensions();
3228 // LordHavoc: report supported extensions
3229 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3231 // clear to black (loading plaque will be seen over this)
3233 qglClearColor(0,0,0,1);CHECKGLERROR
3234 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3237 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3241 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3243 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3246 p = r_refdef.view.frustum + i;
3251 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3255 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3259 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3263 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3267 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3271 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3275 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3279 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3287 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3291 for (i = 0;i < numplanes;i++)
3298 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3302 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3306 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3310 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3314 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3318 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3322 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3326 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3334 //==================================================================================
3336 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3339 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3340 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3341 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3344 typedef struct r_animcache_entity_s
3351 qboolean wantnormals;
3352 qboolean wanttangents;
3354 r_animcache_entity_t;
3356 typedef struct r_animcache_s
3358 r_animcache_entity_t entity[MAX_EDICTS];
3364 static r_animcache_t r_animcachestate;
3366 void R_AnimCache_Free(void)
3369 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3371 r_animcachestate.entity[idx].maxvertices = 0;
3372 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3373 r_animcachestate.entity[idx].vertex3f = NULL;
3374 r_animcachestate.entity[idx].normal3f = NULL;
3375 r_animcachestate.entity[idx].svector3f = NULL;
3376 r_animcachestate.entity[idx].tvector3f = NULL;
3378 r_animcachestate.currentindex = 0;
3379 r_animcachestate.maxindex = 0;
3382 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3386 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3388 if (cache->maxvertices >= numvertices)
3391 // Release existing memory
3392 if (cache->vertex3f)
3393 Mem_Free(cache->vertex3f);
3395 // Pad by 1024 verts
3396 cache->maxvertices = (numvertices + 1023) & ~1023;
3397 arraySize = cache->maxvertices * 3;
3399 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3400 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3401 r_animcachestate.entity[cacheIdx].vertex3f = base;
3402 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3403 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3404 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3406 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3409 void R_AnimCache_NewFrame(void)
3413 if (r_animcache.integer && r_drawentities.integer)
3414 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3415 else if (r_animcachestate.maxindex)
3418 r_animcachestate.currentindex = 0;
3420 for (i = 0;i < r_refdef.scene.numentities;i++)
3421 r_refdef.scene.entities[i]->animcacheindex = -1;
3424 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3426 dp_model_t *model = ent->model;
3427 r_animcache_entity_t *c;
3428 // see if it's already cached this frame
3429 if (ent->animcacheindex >= 0)
3431 // add normals/tangents if needed
3432 c = r_animcachestate.entity + ent->animcacheindex;
3434 wantnormals = false;
3435 if (c->wanttangents)
3436 wanttangents = false;
3437 if (wantnormals || wanttangents)
3438 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3442 // see if this ent is worth caching
3443 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3445 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3447 // assign it a cache entry and make sure the arrays are big enough
3448 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3449 ent->animcacheindex = r_animcachestate.currentindex++;
3450 c = r_animcachestate.entity + ent->animcacheindex;
3451 c->wantnormals = wantnormals;
3452 c->wanttangents = wanttangents;
3453 model->AnimateVertices(model, ent->frameblend, ent->skeleton, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3458 void R_AnimCache_CacheVisibleEntities(void)
3461 qboolean wantnormals;
3462 qboolean wanttangents;
3464 if (!r_animcachestate.maxindex)
3467 wantnormals = !r_showsurfaces.integer;
3468 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3470 // TODO: thread this?
3472 for (i = 0;i < r_refdef.scene.numentities;i++)
3474 if (!r_refdef.viewcache.entityvisible[i])
3476 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3480 //==================================================================================
3482 static void R_View_UpdateEntityLighting (void)
3485 entity_render_t *ent;
3486 vec3_t tempdiffusenormal, avg;
3487 vec_t f, fa, fd, fdd;
3489 for (i = 0;i < r_refdef.scene.numentities;i++)
3491 ent = r_refdef.scene.entities[i];
3493 // skip unseen models
3494 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3498 if (ent->model && ent->model->brush.num_leafs)
3500 // TODO: use modellight for r_ambient settings on world?
3501 VectorSet(ent->modellight_ambient, 0, 0, 0);
3502 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3503 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3507 // fetch the lighting from the worldmodel data
3508 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));
3509 VectorClear(ent->modellight_diffuse);
3510 VectorClear(tempdiffusenormal);
3511 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3514 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3515 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3516 if(ent->flags & RENDER_EQUALIZE)
3518 // first fix up ambient lighting...
3519 if(r_equalize_entities_minambient.value > 0)
3521 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3524 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3525 if(fa < r_equalize_entities_minambient.value * fd)
3528 // fa'/fd' = minambient
3529 // fa'+0.25*fd' = fa+0.25*fd
3531 // fa' = fd' * minambient
3532 // fd'*(0.25+minambient) = fa+0.25*fd
3534 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3535 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3537 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3538 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
3539 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3540 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3545 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3547 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3548 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3551 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3552 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3553 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3559 VectorSet(ent->modellight_ambient, 1, 1, 1);
3561 // move the light direction into modelspace coordinates for lighting code
3562 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3563 if(VectorLength2(ent->modellight_lightdir) == 0)
3564 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3565 VectorNormalize(ent->modellight_lightdir);
3569 #define MAX_LINEOFSIGHTTRACES 64
3571 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3574 vec3_t boxmins, boxmaxs;
3577 dp_model_t *model = r_refdef.scene.worldmodel;
3579 if (!model || !model->brush.TraceLineOfSight)
3582 // expand the box a little
3583 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3584 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3585 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3586 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3587 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3588 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3591 VectorCopy(eye, start);
3592 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3593 if (model->brush.TraceLineOfSight(model, start, end))
3596 // try various random positions
3597 for (i = 0;i < numsamples;i++)
3599 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3600 if (model->brush.TraceLineOfSight(model, start, end))
3608 static void R_View_UpdateEntityVisible (void)
3613 entity_render_t *ent;
3615 if (!r_drawentities.integer)
3618 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3619 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3621 // worldmodel can check visibility
3622 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3623 for (i = 0;i < r_refdef.scene.numentities;i++)
3625 ent = r_refdef.scene.entities[i];
3626 if (!(ent->flags & renderimask))
3627 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)))
3628 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))
3629 r_refdef.viewcache.entityvisible[i] = true;
3631 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3633 for (i = 0;i < r_refdef.scene.numentities;i++)
3635 ent = r_refdef.scene.entities[i];
3636 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3638 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3640 continue; // temp entities do pvs only
3641 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3642 ent->last_trace_visibility = realtime;
3643 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3644 r_refdef.viewcache.entityvisible[i] = 0;
3651 // no worldmodel or it can't check visibility
3652 for (i = 0;i < r_refdef.scene.numentities;i++)
3654 ent = r_refdef.scene.entities[i];
3655 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));
3660 /// only used if skyrendermasked, and normally returns false
3661 int R_DrawBrushModelsSky (void)
3664 entity_render_t *ent;
3666 if (!r_drawentities.integer)
3670 for (i = 0;i < r_refdef.scene.numentities;i++)
3672 if (!r_refdef.viewcache.entityvisible[i])
3674 ent = r_refdef.scene.entities[i];
3675 if (!ent->model || !ent->model->DrawSky)
3677 ent->model->DrawSky(ent);
3683 static void R_DrawNoModel(entity_render_t *ent);
3684 static void R_DrawModels(void)
3687 entity_render_t *ent;
3689 if (!r_drawentities.integer)
3692 for (i = 0;i < r_refdef.scene.numentities;i++)
3694 if (!r_refdef.viewcache.entityvisible[i])
3696 ent = r_refdef.scene.entities[i];
3697 r_refdef.stats.entities++;
3698 if (ent->model && ent->model->Draw != NULL)
3699 ent->model->Draw(ent);
3705 static void R_DrawModelsDepth(void)
3708 entity_render_t *ent;
3710 if (!r_drawentities.integer)
3713 for (i = 0;i < r_refdef.scene.numentities;i++)
3715 if (!r_refdef.viewcache.entityvisible[i])
3717 ent = r_refdef.scene.entities[i];
3718 if (ent->model && ent->model->DrawDepth != NULL)
3719 ent->model->DrawDepth(ent);
3723 static void R_DrawModelsDebug(void)
3726 entity_render_t *ent;
3728 if (!r_drawentities.integer)
3731 for (i = 0;i < r_refdef.scene.numentities;i++)
3733 if (!r_refdef.viewcache.entityvisible[i])
3735 ent = r_refdef.scene.entities[i];
3736 if (ent->model && ent->model->DrawDebug != NULL)
3737 ent->model->DrawDebug(ent);
3741 static void R_DrawModelsAddWaterPlanes(void)
3744 entity_render_t *ent;
3746 if (!r_drawentities.integer)
3749 for (i = 0;i < r_refdef.scene.numentities;i++)
3751 if (!r_refdef.viewcache.entityvisible[i])
3753 ent = r_refdef.scene.entities[i];
3754 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3755 ent->model->DrawAddWaterPlanes(ent);
3759 static void R_View_SetFrustum(void)
3762 double slopex, slopey;
3763 vec3_t forward, left, up, origin;
3765 // we can't trust r_refdef.view.forward and friends in reflected scenes
3766 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3769 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3770 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3771 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3772 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3773 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3774 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3775 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3776 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3777 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3778 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3779 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3780 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3784 zNear = r_refdef.nearclip;
3785 nudge = 1.0 - 1.0 / (1<<23);
3786 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3787 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3788 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3789 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3790 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3791 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3792 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3793 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3799 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3800 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3801 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3802 r_refdef.view.frustum[0].dist = m[15] - m[12];
3804 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3805 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3806 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3807 r_refdef.view.frustum[1].dist = m[15] + m[12];
3809 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3810 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3811 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3812 r_refdef.view.frustum[2].dist = m[15] - m[13];
3814 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3815 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3816 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3817 r_refdef.view.frustum[3].dist = m[15] + m[13];
3819 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3820 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3821 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3822 r_refdef.view.frustum[4].dist = m[15] - m[14];
3824 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3825 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3826 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3827 r_refdef.view.frustum[5].dist = m[15] + m[14];
3830 if (r_refdef.view.useperspective)
3832 slopex = 1.0 / r_refdef.view.frustum_x;
3833 slopey = 1.0 / r_refdef.view.frustum_y;
3834 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3835 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3836 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3837 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3838 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3840 // Leaving those out was a mistake, those were in the old code, and they
3841 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3842 // I couldn't reproduce it after adding those normalizations. --blub
3843 VectorNormalize(r_refdef.view.frustum[0].normal);
3844 VectorNormalize(r_refdef.view.frustum[1].normal);
3845 VectorNormalize(r_refdef.view.frustum[2].normal);
3846 VectorNormalize(r_refdef.view.frustum[3].normal);
3848 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3849 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
3850 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
3851 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]);
3852 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]);
3854 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3855 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3856 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3857 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3858 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3862 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3863 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3864 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3865 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3866 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3867 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3868 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3869 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3870 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3871 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3873 r_refdef.view.numfrustumplanes = 5;
3875 if (r_refdef.view.useclipplane)
3877 r_refdef.view.numfrustumplanes = 6;
3878 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3881 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3882 PlaneClassify(r_refdef.view.frustum + i);
3884 // LordHavoc: note to all quake engine coders, Quake had a special case
3885 // for 90 degrees which assumed a square view (wrong), so I removed it,
3886 // Quake2 has it disabled as well.
3888 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3889 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3890 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3891 //PlaneClassify(&frustum[0]);
3893 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3894 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3895 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3896 //PlaneClassify(&frustum[1]);
3898 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3899 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3900 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3901 //PlaneClassify(&frustum[2]);
3903 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3904 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3905 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3906 //PlaneClassify(&frustum[3]);
3909 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3910 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3911 //PlaneClassify(&frustum[4]);
3914 void R_View_Update(void)
3916 R_Main_ResizeViewCache();
3917 R_View_SetFrustum();
3918 R_View_WorldVisibility(r_refdef.view.useclipplane);
3919 R_View_UpdateEntityVisible();
3920 R_View_UpdateEntityLighting();
3923 void R_SetupView(qboolean allowwaterclippingplane)
3925 const double *customclipplane = NULL;
3927 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3929 // LordHavoc: couldn't figure out how to make this approach the
3930 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3931 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3932 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3933 dist = r_refdef.view.clipplane.dist;
3934 plane[0] = r_refdef.view.clipplane.normal[0];
3935 plane[1] = r_refdef.view.clipplane.normal[1];
3936 plane[2] = r_refdef.view.clipplane.normal[2];
3938 customclipplane = plane;
3941 if (!r_refdef.view.useperspective)
3942 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);
3943 else if (vid.stencil && r_useinfinitefarclip.integer)
3944 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);
3946 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);
3947 R_SetViewport(&r_refdef.view.viewport);
3950 void R_ResetViewRendering2D(void)
3952 r_viewport_t viewport;
3955 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3956 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);
3957 R_SetViewport(&viewport);
3958 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3959 GL_Color(1, 1, 1, 1);
3960 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3961 GL_BlendFunc(GL_ONE, GL_ZERO);
3962 GL_AlphaTest(false);
3963 GL_ScissorTest(false);
3964 GL_DepthMask(false);
3965 GL_DepthRange(0, 1);
3966 GL_DepthTest(false);
3967 R_Mesh_Matrix(&identitymatrix);
3968 R_Mesh_ResetTextureState();
3969 GL_PolygonOffset(0, 0);
3970 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3971 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3972 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3973 qglStencilMask(~0);CHECKGLERROR
3974 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3975 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3976 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3977 R_SetupGenericShader(true);
3980 void R_ResetViewRendering3D(void)
3985 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3986 GL_Color(1, 1, 1, 1);
3987 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3988 GL_BlendFunc(GL_ONE, GL_ZERO);
3989 GL_AlphaTest(false);
3990 GL_ScissorTest(true);
3992 GL_DepthRange(0, 1);
3994 R_Mesh_Matrix(&identitymatrix);
3995 R_Mesh_ResetTextureState();
3996 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3997 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3998 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3999 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4000 qglStencilMask(~0);CHECKGLERROR
4001 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4002 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4003 GL_CullFace(r_refdef.view.cullface_back);
4004 R_SetupGenericShader(true);
4007 void R_RenderScene(void);
4008 void R_RenderWaterPlanes(void);
4010 static void R_Water_StartFrame(void)
4013 int waterwidth, waterheight, texturewidth, textureheight;
4014 r_waterstate_waterplane_t *p;
4016 // set waterwidth and waterheight to the water resolution that will be
4017 // used (often less than the screen resolution for faster rendering)
4018 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
4019 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
4021 // calculate desired texture sizes
4022 // can't use water if the card does not support the texture size
4023 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)
4024 texturewidth = textureheight = waterwidth = waterheight = 0;
4025 else if (vid.support.arb_texture_non_power_of_two)
4027 texturewidth = waterwidth;
4028 textureheight = waterheight;
4032 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4033 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4036 // allocate textures as needed
4037 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4039 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4040 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4042 if (p->texture_refraction)
4043 R_FreeTexture(p->texture_refraction);
4044 p->texture_refraction = NULL;
4045 if (p->texture_reflection)
4046 R_FreeTexture(p->texture_reflection);
4047 p->texture_reflection = NULL;
4049 memset(&r_waterstate, 0, sizeof(r_waterstate));
4050 r_waterstate.texturewidth = texturewidth;
4051 r_waterstate.textureheight = textureheight;
4054 if (r_waterstate.texturewidth)
4056 r_waterstate.enabled = true;
4058 // when doing a reduced render (HDR) we want to use a smaller area
4059 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4060 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4062 // set up variables that will be used in shader setup
4063 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4064 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4065 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4066 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4069 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4070 r_waterstate.numwaterplanes = 0;
4073 void R_Water_AddWaterPlane(msurface_t *surface)
4075 int triangleindex, planeindex;
4081 r_waterstate_waterplane_t *p;
4082 texture_t *t = R_GetCurrentTexture(surface->texture);
4083 // just use the first triangle with a valid normal for any decisions
4084 VectorClear(normal);
4085 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4087 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4088 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4089 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4090 TriangleNormal(vert[0], vert[1], vert[2], normal);
4091 if (VectorLength2(normal) >= 0.001)
4095 VectorCopy(normal, plane.normal);
4096 VectorNormalize(plane.normal);
4097 plane.dist = DotProduct(vert[0], plane.normal);
4098 PlaneClassify(&plane);
4099 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4101 // skip backfaces (except if nocullface is set)
4102 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4104 VectorNegate(plane.normal, plane.normal);
4106 PlaneClassify(&plane);
4110 // find a matching plane if there is one
4111 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4112 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4114 if (planeindex >= r_waterstate.maxwaterplanes)
4115 return; // nothing we can do, out of planes
4117 // if this triangle does not fit any known plane rendered this frame, add one
4118 if (planeindex >= r_waterstate.numwaterplanes)
4120 // store the new plane
4121 r_waterstate.numwaterplanes++;
4123 // clear materialflags and pvs
4124 p->materialflags = 0;
4125 p->pvsvalid = false;
4127 // merge this surface's materialflags into the waterplane
4128 p->materialflags |= t->currentmaterialflags;
4129 // merge this surface's PVS into the waterplane
4130 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4131 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4132 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4134 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4139 static void R_Water_ProcessPlanes(void)
4141 r_refdef_view_t originalview;
4142 r_refdef_view_t myview;
4144 r_waterstate_waterplane_t *p;
4146 originalview = r_refdef.view;
4148 // make sure enough textures are allocated
4149 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4151 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4153 if (!p->texture_refraction)
4154 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);
4155 if (!p->texture_refraction)
4159 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4161 if (!p->texture_reflection)
4162 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);
4163 if (!p->texture_reflection)
4169 r_refdef.view = originalview;
4170 r_refdef.view.showdebug = false;
4171 r_refdef.view.width = r_waterstate.waterwidth;
4172 r_refdef.view.height = r_waterstate.waterheight;
4173 r_refdef.view.useclipplane = true;
4174 myview = r_refdef.view;
4175 r_waterstate.renderingscene = true;
4176 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4178 // render the normal view scene and copy into texture
4179 // (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)
4180 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4182 r_refdef.view = myview;
4183 r_refdef.view.clipplane = p->plane;
4184 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4185 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4186 PlaneClassify(&r_refdef.view.clipplane);
4188 R_ResetViewRendering3D();
4189 R_ClearScreen(r_refdef.fogenabled);
4193 // copy view into the screen texture
4194 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4195 GL_ActiveTexture(0);
4197 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
4200 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4202 r_refdef.view = myview;
4203 // render reflected scene and copy into texture
4204 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4205 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4206 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4207 r_refdef.view.clipplane = p->plane;
4208 // reverse the cullface settings for this render
4209 r_refdef.view.cullface_front = GL_FRONT;
4210 r_refdef.view.cullface_back = GL_BACK;
4211 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4213 r_refdef.view.usecustompvs = true;
4215 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4217 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4220 R_ResetViewRendering3D();
4221 R_ClearScreen(r_refdef.fogenabled);
4225 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4226 GL_ActiveTexture(0);
4228 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
4231 r_waterstate.renderingscene = false;
4232 r_refdef.view = originalview;
4233 R_ResetViewRendering3D();
4234 R_ClearScreen(r_refdef.fogenabled);
4238 r_refdef.view = originalview;
4239 r_waterstate.renderingscene = false;
4240 Cvar_SetValueQuick(&r_water, 0);
4241 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4245 void R_Bloom_StartFrame(void)
4247 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4249 // set bloomwidth and bloomheight to the bloom resolution that will be
4250 // used (often less than the screen resolution for faster rendering)
4251 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4252 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4253 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4254 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
4255 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
4257 // calculate desired texture sizes
4258 if (vid.support.arb_texture_non_power_of_two)
4260 screentexturewidth = r_refdef.view.width;
4261 screentextureheight = r_refdef.view.height;
4262 bloomtexturewidth = r_bloomstate.bloomwidth;
4263 bloomtextureheight = r_bloomstate.bloomheight;
4267 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4268 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4269 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4270 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4273 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))
4275 Cvar_SetValueQuick(&r_hdr, 0);
4276 Cvar_SetValueQuick(&r_bloom, 0);
4277 Cvar_SetValueQuick(&r_motionblur, 0);
4278 Cvar_SetValueQuick(&r_damageblur, 0);
4281 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)))
4282 screentexturewidth = screentextureheight = 0;
4283 if (!r_hdr.integer && !r_bloom.integer)
4284 bloomtexturewidth = bloomtextureheight = 0;
4286 // allocate textures as needed
4287 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4289 if (r_bloomstate.texture_screen)
4290 R_FreeTexture(r_bloomstate.texture_screen);
4291 r_bloomstate.texture_screen = NULL;
4292 r_bloomstate.screentexturewidth = screentexturewidth;
4293 r_bloomstate.screentextureheight = screentextureheight;
4294 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4295 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);
4297 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4299 if (r_bloomstate.texture_bloom)
4300 R_FreeTexture(r_bloomstate.texture_bloom);
4301 r_bloomstate.texture_bloom = NULL;
4302 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4303 r_bloomstate.bloomtextureheight = bloomtextureheight;
4304 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4305 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);
4308 // when doing a reduced render (HDR) we want to use a smaller area
4309 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4310 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4311 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4312 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4313 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4315 // set up a texcoord array for the full resolution screen image
4316 // (we have to keep this around to copy back during final render)
4317 r_bloomstate.screentexcoord2f[0] = 0;
4318 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4319 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4320 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4321 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4322 r_bloomstate.screentexcoord2f[5] = 0;
4323 r_bloomstate.screentexcoord2f[6] = 0;
4324 r_bloomstate.screentexcoord2f[7] = 0;
4326 // set up a texcoord array for the reduced resolution bloom image
4327 // (which will be additive blended over the screen image)
4328 r_bloomstate.bloomtexcoord2f[0] = 0;
4329 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4330 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4331 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4332 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4333 r_bloomstate.bloomtexcoord2f[5] = 0;
4334 r_bloomstate.bloomtexcoord2f[6] = 0;
4335 r_bloomstate.bloomtexcoord2f[7] = 0;
4337 if (r_hdr.integer || r_bloom.integer)
4339 r_bloomstate.enabled = true;
4340 r_bloomstate.hdr = r_hdr.integer != 0;
4343 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);
4346 void R_Bloom_CopyBloomTexture(float colorscale)
4348 r_refdef.stats.bloom++;
4350 // scale down screen texture to the bloom texture size
4352 R_SetViewport(&r_bloomstate.viewport);
4353 GL_BlendFunc(GL_ONE, GL_ZERO);
4354 GL_Color(colorscale, colorscale, colorscale, 1);
4355 // TODO: optimize with multitexture or GLSL
4356 R_SetupGenericShader(true);
4357 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4358 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4359 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4360 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4362 // we now have a bloom image in the framebuffer
4363 // copy it into the bloom image texture for later processing
4364 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4365 GL_ActiveTexture(0);
4367 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4368 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4371 void R_Bloom_CopyHDRTexture(void)
4373 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4374 GL_ActiveTexture(0);
4376 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
4377 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4380 void R_Bloom_MakeTexture(void)
4383 float xoffset, yoffset, r, brighten;
4385 r_refdef.stats.bloom++;
4387 R_ResetViewRendering2D();
4388 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4389 R_Mesh_ColorPointer(NULL, 0, 0);
4390 R_SetupGenericShader(true);
4392 // we have a bloom image in the framebuffer
4394 R_SetViewport(&r_bloomstate.viewport);
4396 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4399 r = bound(0, r_bloom_colorexponent.value / x, 1);
4400 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4401 GL_Color(r, r, r, 1);
4402 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4403 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4404 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4405 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4407 // copy the vertically blurred bloom view to a texture
4408 GL_ActiveTexture(0);
4410 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4411 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4414 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4415 brighten = r_bloom_brighten.value;
4417 brighten *= r_hdr_range.value;
4418 brighten = sqrt(brighten);
4420 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4421 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4422 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4424 for (dir = 0;dir < 2;dir++)
4426 // blend on at multiple vertical offsets to achieve a vertical blur
4427 // TODO: do offset blends using GLSL
4428 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4429 GL_BlendFunc(GL_ONE, GL_ZERO);
4430 for (x = -range;x <= range;x++)
4432 if (!dir){xoffset = 0;yoffset = x;}
4433 else {xoffset = x;yoffset = 0;}
4434 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4435 yoffset /= (float)r_bloomstate.bloomtextureheight;
4436 // compute a texcoord array with the specified x and y offset
4437 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4438 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4439 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4440 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4441 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4442 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4443 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4444 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4445 // this r value looks like a 'dot' particle, fading sharply to
4446 // black at the edges
4447 // (probably not realistic but looks good enough)
4448 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4449 //r = brighten/(range*2+1);
4450 r = brighten / (range * 2 + 1);
4452 r *= (1 - x*x/(float)(range*range));
4453 GL_Color(r, r, r, 1);
4454 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4455 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4456 GL_BlendFunc(GL_ONE, GL_ONE);
4459 // copy the vertically blurred bloom view to a texture
4460 GL_ActiveTexture(0);
4462 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4463 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4466 // apply subtract last
4467 // (just like it would be in a GLSL shader)
4468 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
4470 GL_BlendFunc(GL_ONE, GL_ZERO);
4471 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4472 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4473 GL_Color(1, 1, 1, 1);
4474 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4475 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4477 GL_BlendFunc(GL_ONE, GL_ONE);
4478 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4479 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4480 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4481 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4482 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4483 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4484 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4486 // copy the darkened bloom view to a texture
4487 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4488 GL_ActiveTexture(0);
4490 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4491 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4495 void R_HDR_RenderBloomTexture(void)
4497 int oldwidth, oldheight;
4498 float oldcolorscale;
4500 oldcolorscale = r_refdef.view.colorscale;
4501 oldwidth = r_refdef.view.width;
4502 oldheight = r_refdef.view.height;
4503 r_refdef.view.width = r_bloomstate.bloomwidth;
4504 r_refdef.view.height = r_bloomstate.bloomheight;
4506 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4507 // TODO: add exposure compensation features
4508 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4510 r_refdef.view.showdebug = false;
4511 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4513 R_ResetViewRendering3D();
4515 R_ClearScreen(r_refdef.fogenabled);
4516 if (r_timereport_active)
4517 R_TimeReport("HDRclear");
4520 if (r_timereport_active)
4521 R_TimeReport("visibility");
4523 // only do secondary renders with HDR if r_hdr is 2 or higher
4524 r_waterstate.numwaterplanes = 0;
4525 if (r_waterstate.enabled && r_hdr.integer >= 2)
4526 R_RenderWaterPlanes();
4528 r_refdef.view.showdebug = true;
4530 r_waterstate.numwaterplanes = 0;
4532 R_ResetViewRendering2D();
4534 R_Bloom_CopyHDRTexture();
4535 R_Bloom_MakeTexture();
4537 // restore the view settings
4538 r_refdef.view.width = oldwidth;
4539 r_refdef.view.height = oldheight;
4540 r_refdef.view.colorscale = oldcolorscale;
4542 R_ResetViewRendering3D();
4544 R_ClearScreen(r_refdef.fogenabled);
4545 if (r_timereport_active)
4546 R_TimeReport("viewclear");
4549 static void R_BlendView(void)
4551 if (r_bloomstate.texture_screen)
4553 // make sure the buffer is available
4554 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4556 R_ResetViewRendering2D();
4557 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4558 R_Mesh_ColorPointer(NULL, 0, 0);
4559 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4560 GL_ActiveTexture(0);CHECKGLERROR
4562 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4564 // declare variables
4566 static float avgspeed;
4568 speed = VectorLength(cl.movement_velocity);
4570 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4571 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4573 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4574 speed = bound(0, speed, 1);
4575 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4577 // calculate values into a standard alpha
4578 cl.motionbluralpha = 1 - exp(-
4580 (r_motionblur.value * speed / 80)
4582 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4585 max(0.0001, cl.time - cl.oldtime) // fps independent
4588 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4589 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4591 if (cl.motionbluralpha > 0)
4593 R_SetupGenericShader(true);
4594 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4595 GL_Color(1, 1, 1, cl.motionbluralpha);
4596 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4597 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4598 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4599 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4603 // copy view into the screen texture
4604 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
4605 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4608 if (r_glsl.integer && vid.support.arb_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4610 unsigned int permutation =
4611 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4612 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4613 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4614 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4615 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4617 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4619 // render simple bloom effect
4620 // copy the screen and shrink it and darken it for the bloom process
4621 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4622 // make the bloom texture
4623 R_Bloom_MakeTexture();
4626 R_ResetViewRendering2D();
4627 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4628 R_Mesh_ColorPointer(NULL, 0, 0);
4629 GL_Color(1, 1, 1, 1);
4630 GL_BlendFunc(GL_ONE, GL_ZERO);
4631 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4632 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4633 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4634 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4635 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4636 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4637 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4638 if (r_glsl_permutation->loc_TintColor >= 0)
4639 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4640 if (r_glsl_permutation->loc_ClientTime >= 0)
4641 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4642 if (r_glsl_permutation->loc_PixelSize >= 0)
4643 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4644 if (r_glsl_permutation->loc_UserVec1 >= 0)
4646 float a=0, b=0, c=0, d=0;
4647 #if _MSC_VER >= 1400
4648 #define sscanf sscanf_s
4650 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4651 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4653 if (r_glsl_permutation->loc_UserVec2 >= 0)
4655 float a=0, b=0, c=0, d=0;
4656 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4657 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4659 if (r_glsl_permutation->loc_UserVec3 >= 0)
4661 float a=0, b=0, c=0, d=0;
4662 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4663 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4665 if (r_glsl_permutation->loc_UserVec4 >= 0)
4667 float a=0, b=0, c=0, d=0;
4668 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4669 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4671 if (r_glsl_permutation->loc_Saturation >= 0)
4672 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4673 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4674 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4680 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4682 // render high dynamic range bloom effect
4683 // the bloom texture was made earlier this render, so we just need to
4684 // blend it onto the screen...
4685 R_ResetViewRendering2D();
4686 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4687 R_Mesh_ColorPointer(NULL, 0, 0);
4688 R_SetupGenericShader(true);
4689 GL_Color(1, 1, 1, 1);
4690 GL_BlendFunc(GL_ONE, GL_ONE);
4691 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4692 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4693 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4694 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4696 else if (r_bloomstate.texture_bloom)
4698 // render simple bloom effect
4699 // copy the screen and shrink it and darken it for the bloom process
4700 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4701 // make the bloom texture
4702 R_Bloom_MakeTexture();
4703 // put the original screen image back in place and blend the bloom
4705 R_ResetViewRendering2D();
4706 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4707 R_Mesh_ColorPointer(NULL, 0, 0);
4708 GL_Color(1, 1, 1, 1);
4709 GL_BlendFunc(GL_ONE, GL_ZERO);
4710 // do both in one pass if possible
4711 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4712 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4713 if (r_textureunits.integer >= 2 && gl_combine.integer)
4715 R_SetupGenericTwoTextureShader(GL_ADD);
4716 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4717 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4721 R_SetupGenericShader(true);
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;
4724 // now blend on the bloom texture
4725 GL_BlendFunc(GL_ONE, GL_ONE);
4726 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4727 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4729 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4730 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4732 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4734 // apply a color tint to the whole view
4735 R_ResetViewRendering2D();
4736 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4737 R_Mesh_ColorPointer(NULL, 0, 0);
4738 R_SetupGenericShader(false);
4739 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4740 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4741 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4745 matrix4x4_t r_waterscrollmatrix;
4747 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4749 if (r_refdef.fog_density)
4751 r_refdef.fogcolor[0] = r_refdef.fog_red;
4752 r_refdef.fogcolor[1] = r_refdef.fog_green;
4753 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4755 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4756 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4757 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4758 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4762 VectorCopy(r_refdef.fogcolor, fogvec);
4763 // color.rgb *= ContrastBoost * SceneBrightness;
4764 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4765 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4766 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4767 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4772 void R_UpdateVariables(void)
4776 r_refdef.scene.ambient = r_ambient.value;
4778 r_refdef.farclip = r_farclip_base.value;
4779 if (r_refdef.scene.worldmodel)
4780 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
4781 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4783 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4784 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4785 r_refdef.polygonfactor = 0;
4786 r_refdef.polygonoffset = 0;
4787 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4788 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4790 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4791 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
4792 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4793 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
4794 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4795 if (r_showsurfaces.integer)
4797 r_refdef.scene.rtworld = false;
4798 r_refdef.scene.rtworldshadows = false;
4799 r_refdef.scene.rtdlight = false;
4800 r_refdef.scene.rtdlightshadows = false;
4801 r_refdef.lightmapintensity = 0;
4804 if (gamemode == GAME_NEHAHRA)
4806 if (gl_fogenable.integer)
4808 r_refdef.oldgl_fogenable = true;
4809 r_refdef.fog_density = gl_fogdensity.value;
4810 r_refdef.fog_red = gl_fogred.value;
4811 r_refdef.fog_green = gl_foggreen.value;
4812 r_refdef.fog_blue = gl_fogblue.value;
4813 r_refdef.fog_alpha = 1;
4814 r_refdef.fog_start = 0;
4815 r_refdef.fog_end = gl_skyclip.value;
4816 r_refdef.fog_height = 1<<30;
4817 r_refdef.fog_fadedepth = 128;
4819 else if (r_refdef.oldgl_fogenable)
4821 r_refdef.oldgl_fogenable = false;
4822 r_refdef.fog_density = 0;
4823 r_refdef.fog_red = 0;
4824 r_refdef.fog_green = 0;
4825 r_refdef.fog_blue = 0;
4826 r_refdef.fog_alpha = 0;
4827 r_refdef.fog_start = 0;
4828 r_refdef.fog_end = 0;
4829 r_refdef.fog_height = 1<<30;
4830 r_refdef.fog_fadedepth = 128;
4834 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4835 r_refdef.fog_start = max(0, r_refdef.fog_start);
4836 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4838 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4840 if (r_refdef.fog_density && r_drawfog.integer)
4842 r_refdef.fogenabled = true;
4843 // this is the point where the fog reaches 0.9986 alpha, which we
4844 // consider a good enough cutoff point for the texture
4845 // (0.9986 * 256 == 255.6)
4846 if (r_fog_exp2.integer)
4847 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4849 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4850 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4851 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4852 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4853 // fog color was already set
4854 // update the fog texture
4855 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)
4856 R_BuildFogTexture();
4859 r_refdef.fogenabled = false;
4861 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4863 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4865 // build GLSL gamma texture
4866 #define RAMPWIDTH 256
4867 unsigned short ramp[RAMPWIDTH * 3];
4868 unsigned char rampbgr[RAMPWIDTH][4];
4871 r_texture_gammaramps_serial = vid_gammatables_serial;
4873 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4874 for(i = 0; i < RAMPWIDTH; ++i)
4876 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4877 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4878 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4881 if (r_texture_gammaramps)
4883 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4887 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);
4893 // remove GLSL gamma texture
4897 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4898 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4904 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4905 if( scenetype != r_currentscenetype ) {
4906 // store the old scenetype
4907 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4908 r_currentscenetype = scenetype;
4909 // move in the new scene
4910 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4919 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4921 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4922 if( scenetype == r_currentscenetype ) {
4923 return &r_refdef.scene;
4925 return &r_scenes_store[ scenetype ];
4934 void R_RenderView(void)
4936 if (r_timereport_active)
4937 R_TimeReport("start");
4938 r_frame++; // used only by R_GetCurrentTexture
4939 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4941 R_AnimCache_NewFrame();
4943 if (r_refdef.view.isoverlay)
4945 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4946 GL_Clear( GL_DEPTH_BUFFER_BIT );
4947 R_TimeReport("depthclear");
4949 r_refdef.view.showdebug = false;
4951 r_waterstate.enabled = false;
4952 r_waterstate.numwaterplanes = 0;
4960 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4961 return; //Host_Error ("R_RenderView: NULL worldmodel");
4963 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4965 // break apart the view matrix into vectors for various purposes
4966 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4967 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4968 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4969 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4970 // make an inverted copy of the view matrix for tracking sprites
4971 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4973 R_Shadow_UpdateWorldLightSelection();
4975 R_Bloom_StartFrame();
4976 R_Water_StartFrame();
4979 if (r_timereport_active)
4980 R_TimeReport("viewsetup");
4982 R_ResetViewRendering3D();
4984 if (r_refdef.view.clear || r_refdef.fogenabled)
4986 R_ClearScreen(r_refdef.fogenabled);
4987 if (r_timereport_active)
4988 R_TimeReport("viewclear");
4990 r_refdef.view.clear = true;
4992 // this produces a bloom texture to be used in R_BlendView() later
4993 if (r_hdr.integer && r_bloomstate.bloomwidth)
4994 R_HDR_RenderBloomTexture();
4996 r_refdef.view.showdebug = true;
4999 if (r_timereport_active)
5000 R_TimeReport("visibility");
5002 r_waterstate.numwaterplanes = 0;
5003 if (r_waterstate.enabled)
5004 R_RenderWaterPlanes();
5007 r_waterstate.numwaterplanes = 0;
5010 if (r_timereport_active)
5011 R_TimeReport("blendview");
5013 GL_Scissor(0, 0, vid.width, vid.height);
5014 GL_ScissorTest(false);
5018 void R_RenderWaterPlanes(void)
5020 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5022 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5023 if (r_timereport_active)
5024 R_TimeReport("waterworld");
5027 // don't let sound skip if going slow
5028 if (r_refdef.scene.extraupdate)
5031 R_DrawModelsAddWaterPlanes();
5032 if (r_timereport_active)
5033 R_TimeReport("watermodels");
5035 if (r_waterstate.numwaterplanes)
5037 R_Water_ProcessPlanes();
5038 if (r_timereport_active)
5039 R_TimeReport("waterscenes");
5043 extern void R_DrawLightningBeams (void);
5044 extern void VM_CL_AddPolygonsToMeshQueue (void);
5045 extern void R_DrawPortals (void);
5046 extern cvar_t cl_locs_show;
5047 static void R_DrawLocs(void);
5048 static void R_DrawEntityBBoxes(void);
5049 static void R_DrawModelDecals(void);
5050 extern cvar_t cl_decals_newsystem;
5051 void R_RenderScene(void)
5053 r_refdef.stats.renders++;
5057 // don't let sound skip if going slow
5058 if (r_refdef.scene.extraupdate)
5061 R_MeshQueue_BeginScene();
5065 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);
5067 if (cl.csqc_vidvars.drawworld)
5069 // don't let sound skip if going slow
5070 if (r_refdef.scene.extraupdate)
5073 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5075 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5076 if (r_timereport_active)
5077 R_TimeReport("worldsky");
5080 if (R_DrawBrushModelsSky() && r_timereport_active)
5081 R_TimeReport("bmodelsky");
5083 if (skyrendermasked && skyrenderlater)
5085 // we have to force off the water clipping plane while rendering sky
5092 R_AnimCache_CacheVisibleEntities();
5094 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5096 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5097 if (r_timereport_active)
5098 R_TimeReport("worlddepth");
5100 if (r_depthfirst.integer >= 2)
5102 R_DrawModelsDepth();
5103 if (r_timereport_active)
5104 R_TimeReport("modeldepth");
5107 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5109 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5110 if (r_timereport_active)
5111 R_TimeReport("world");
5114 // don't let sound skip if going slow
5115 if (r_refdef.scene.extraupdate)
5119 if (r_timereport_active)
5120 R_TimeReport("models");
5122 // don't let sound skip if going slow
5123 if (r_refdef.scene.extraupdate)
5126 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5128 R_DrawModelShadows();
5129 R_ResetViewRendering3D();
5130 // don't let sound skip if going slow
5131 if (r_refdef.scene.extraupdate)
5135 R_ShadowVolumeLighting(false);
5136 if (r_timereport_active)
5137 R_TimeReport("rtlights");
5139 // don't let sound skip if going slow
5140 if (r_refdef.scene.extraupdate)
5143 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5145 R_DrawModelShadows();
5146 R_ResetViewRendering3D();
5147 // don't let sound skip if going slow
5148 if (r_refdef.scene.extraupdate)
5152 if (cl.csqc_vidvars.drawworld)
5154 if (cl_decals_newsystem.integer)
5156 R_DrawModelDecals();
5157 if (r_timereport_active)
5158 R_TimeReport("modeldecals");
5163 if (r_timereport_active)
5164 R_TimeReport("decals");
5168 if (r_timereport_active)
5169 R_TimeReport("particles");
5172 if (r_timereport_active)
5173 R_TimeReport("explosions");
5175 R_DrawLightningBeams();
5176 if (r_timereport_active)
5177 R_TimeReport("lightning");
5180 R_SetupGenericShader(true);
5181 VM_CL_AddPolygonsToMeshQueue();
5183 if (r_refdef.view.showdebug)
5185 if (cl_locs_show.integer)
5188 if (r_timereport_active)
5189 R_TimeReport("showlocs");
5192 if (r_drawportals.integer)
5195 if (r_timereport_active)
5196 R_TimeReport("portals");
5199 if (r_showbboxes.value > 0)
5201 R_DrawEntityBBoxes();
5202 if (r_timereport_active)
5203 R_TimeReport("bboxes");
5207 R_SetupGenericShader(true);
5208 R_MeshQueue_RenderTransparent();
5209 if (r_timereport_active)
5210 R_TimeReport("drawtrans");
5212 R_SetupGenericShader(true);
5214 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))
5216 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5217 if (r_timereport_active)
5218 R_TimeReport("worlddebug");
5219 R_DrawModelsDebug();
5220 if (r_timereport_active)
5221 R_TimeReport("modeldebug");
5224 R_SetupGenericShader(true);
5226 if (cl.csqc_vidvars.drawworld)
5229 if (r_timereport_active)
5230 R_TimeReport("coronas");
5233 // don't let sound skip if going slow
5234 if (r_refdef.scene.extraupdate)
5237 R_ResetViewRendering2D();
5240 static const unsigned short bboxelements[36] =
5250 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5253 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5255 RSurf_ActiveWorldEntity();
5257 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5258 GL_DepthMask(false);
5259 GL_DepthRange(0, 1);
5260 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5261 R_Mesh_ResetTextureState();
5263 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5264 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5265 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5266 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5267 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5268 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5269 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5270 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5271 R_FillColors(color4f, 8, cr, cg, cb, ca);
5272 if (r_refdef.fogenabled)
5274 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5276 f1 = RSurf_FogVertex(v);
5278 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5279 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5280 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5283 R_Mesh_VertexPointer(vertex3f, 0, 0);
5284 R_Mesh_ColorPointer(color4f, 0, 0);
5285 R_Mesh_ResetTextureState();
5286 R_SetupGenericShader(false);
5287 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5290 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5294 prvm_edict_t *edict;
5295 prvm_prog_t *prog_save = prog;
5297 // this function draws bounding boxes of server entities
5301 GL_CullFace(GL_NONE);
5302 R_SetupGenericShader(false);
5306 for (i = 0;i < numsurfaces;i++)
5308 edict = PRVM_EDICT_NUM(surfacelist[i]);
5309 switch ((int)edict->fields.server->solid)
5311 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5312 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5313 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5314 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5315 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5316 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5318 color[3] *= r_showbboxes.value;
5319 color[3] = bound(0, color[3], 1);
5320 GL_DepthTest(!r_showdisabledepthtest.integer);
5321 GL_CullFace(r_refdef.view.cullface_front);
5322 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5328 static void R_DrawEntityBBoxes(void)
5331 prvm_edict_t *edict;
5333 prvm_prog_t *prog_save = prog;
5335 // this function draws bounding boxes of server entities
5341 for (i = 0;i < prog->num_edicts;i++)
5343 edict = PRVM_EDICT_NUM(i);
5344 if (edict->priv.server->free)
5346 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5347 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5349 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5351 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5352 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5358 static const int nomodelelement3i[24] =
5370 static const unsigned short nomodelelement3s[24] =
5382 static const float nomodelvertex3f[6*3] =
5392 static const float nomodelcolor4f[6*4] =
5394 0.0f, 0.0f, 0.5f, 1.0f,
5395 0.0f, 0.0f, 0.5f, 1.0f,
5396 0.0f, 0.5f, 0.0f, 1.0f,
5397 0.0f, 0.5f, 0.0f, 1.0f,
5398 0.5f, 0.0f, 0.0f, 1.0f,
5399 0.5f, 0.0f, 0.0f, 1.0f
5402 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5408 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);
5410 // this is only called once per entity so numsurfaces is always 1, and
5411 // surfacelist is always {0}, so this code does not handle batches
5413 if (rsurface.ent_flags & RENDER_ADDITIVE)
5415 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5416 GL_DepthMask(false);
5418 else if (rsurface.ent_color[3] < 1)
5420 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5421 GL_DepthMask(false);
5425 GL_BlendFunc(GL_ONE, GL_ZERO);
5428 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5429 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5430 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5431 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5432 R_SetupGenericShader(false);
5433 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5434 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5435 R_Mesh_ColorPointer(color4f, 0, 0);
5436 for (i = 0, c = color4f;i < 6;i++, c += 4)
5438 c[0] *= rsurface.ent_color[0];
5439 c[1] *= rsurface.ent_color[1];
5440 c[2] *= rsurface.ent_color[2];
5441 c[3] *= rsurface.ent_color[3];
5443 if (r_refdef.fogenabled)
5445 for (i = 0, c = color4f;i < 6;i++, c += 4)
5447 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5449 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5450 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5451 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5454 R_Mesh_ResetTextureState();
5455 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5458 void R_DrawNoModel(entity_render_t *ent)
5461 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5462 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5463 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5465 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5468 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5470 vec3_t right1, right2, diff, normal;
5472 VectorSubtract (org2, org1, normal);
5474 // calculate 'right' vector for start
5475 VectorSubtract (r_refdef.view.origin, org1, diff);
5476 CrossProduct (normal, diff, right1);
5477 VectorNormalize (right1);
5479 // calculate 'right' vector for end
5480 VectorSubtract (r_refdef.view.origin, org2, diff);
5481 CrossProduct (normal, diff, right2);
5482 VectorNormalize (right2);
5484 vert[ 0] = org1[0] + width * right1[0];
5485 vert[ 1] = org1[1] + width * right1[1];
5486 vert[ 2] = org1[2] + width * right1[2];
5487 vert[ 3] = org1[0] - width * right1[0];
5488 vert[ 4] = org1[1] - width * right1[1];
5489 vert[ 5] = org1[2] - width * right1[2];
5490 vert[ 6] = org2[0] - width * right2[0];
5491 vert[ 7] = org2[1] - width * right2[1];
5492 vert[ 8] = org2[2] - width * right2[2];
5493 vert[ 9] = org2[0] + width * right2[0];
5494 vert[10] = org2[1] + width * right2[1];
5495 vert[11] = org2[2] + width * right2[2];
5498 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)
5500 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5501 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5502 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5503 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5504 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5505 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5506 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5507 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5508 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5509 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5510 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5511 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5514 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5519 VectorSet(v, x, y, z);
5520 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5521 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5523 if (i == mesh->numvertices)
5525 if (mesh->numvertices < mesh->maxvertices)
5527 VectorCopy(v, vertex3f);
5528 mesh->numvertices++;
5530 return mesh->numvertices;
5536 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5540 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5541 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5542 e = mesh->element3i + mesh->numtriangles * 3;
5543 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5545 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5546 if (mesh->numtriangles < mesh->maxtriangles)
5551 mesh->numtriangles++;
5553 element[1] = element[2];
5557 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5561 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5562 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5563 e = mesh->element3i + mesh->numtriangles * 3;
5564 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5566 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5567 if (mesh->numtriangles < mesh->maxtriangles)
5572 mesh->numtriangles++;
5574 element[1] = element[2];
5578 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5579 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5581 int planenum, planenum2;
5584 mplane_t *plane, *plane2;
5586 double temppoints[2][256*3];
5587 // figure out how large a bounding box we need to properly compute this brush
5589 for (w = 0;w < numplanes;w++)
5590 maxdist = max(maxdist, fabs(planes[w].dist));
5591 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5592 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5593 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5597 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5598 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5600 if (planenum2 == planenum)
5602 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);
5605 if (tempnumpoints < 3)
5607 // generate elements forming a triangle fan for this polygon
5608 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5612 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)
5614 texturelayer_t *layer;
5615 layer = t->currentlayers + t->currentnumlayers++;
5617 layer->depthmask = depthmask;
5618 layer->blendfunc1 = blendfunc1;
5619 layer->blendfunc2 = blendfunc2;
5620 layer->texture = texture;
5621 layer->texmatrix = *matrix;
5622 layer->color[0] = r * r_refdef.view.colorscale;
5623 layer->color[1] = g * r_refdef.view.colorscale;
5624 layer->color[2] = b * r_refdef.view.colorscale;
5625 layer->color[3] = a;
5628 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5631 index = parms[2] + r_refdef.scene.time * parms[3];
5632 index -= floor(index);
5636 case Q3WAVEFUNC_NONE:
5637 case Q3WAVEFUNC_NOISE:
5638 case Q3WAVEFUNC_COUNT:
5641 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5642 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5643 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5644 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5645 case Q3WAVEFUNC_TRIANGLE:
5647 f = index - floor(index);
5658 return (float)(parms[0] + parms[1] * f);
5661 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5666 matrix4x4_t matrix, temp;
5667 switch(tcmod->tcmod)
5671 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5672 matrix = r_waterscrollmatrix;
5674 matrix = identitymatrix;
5676 case Q3TCMOD_ENTITYTRANSLATE:
5677 // this is used in Q3 to allow the gamecode to control texcoord
5678 // scrolling on the entity, which is not supported in darkplaces yet.
5679 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5681 case Q3TCMOD_ROTATE:
5682 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5683 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5684 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5687 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5689 case Q3TCMOD_SCROLL:
5690 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5692 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5693 w = (int) tcmod->parms[0];
5694 h = (int) tcmod->parms[1];
5695 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5697 idx = (int) floor(f * w * h);
5698 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5700 case Q3TCMOD_STRETCH:
5701 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5702 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5704 case Q3TCMOD_TRANSFORM:
5705 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5706 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5707 VectorSet(tcmat + 6, 0 , 0 , 1);
5708 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5709 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5711 case Q3TCMOD_TURBULENT:
5712 // this is handled in the RSurf_PrepareVertices function
5713 matrix = identitymatrix;
5717 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5720 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5722 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5723 char name[MAX_QPATH];
5724 skinframe_t *skinframe;
5725 unsigned char pixels[296*194];
5726 strlcpy(cache->name, skinname, sizeof(cache->name));
5727 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5728 if (developer_loading.integer)
5729 Con_Printf("loading %s\n", name);
5730 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5731 if (!skinframe || !skinframe->base)
5734 fs_offset_t filesize;
5736 f = FS_LoadFile(name, tempmempool, true, &filesize);
5739 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5740 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5744 cache->skinframe = skinframe;
5747 texture_t *R_GetCurrentTexture(texture_t *t)
5750 const entity_render_t *ent = rsurface.entity;
5751 dp_model_t *model = ent->model;
5752 q3shaderinfo_layer_tcmod_t *tcmod;
5754 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5755 return t->currentframe;
5756 t->update_lastrenderframe = r_frame;
5757 t->update_lastrenderentity = (void *)ent;
5759 // switch to an alternate material if this is a q1bsp animated material
5761 texture_t *texture = t;
5762 int s = rsurface.ent_skinnum;
5763 if ((unsigned int)s >= (unsigned int)model->numskins)
5765 if (model->skinscenes)
5767 if (model->skinscenes[s].framecount > 1)
5768 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5770 s = model->skinscenes[s].firstframe;
5773 t = t + s * model->num_surfaces;
5776 // use an alternate animation if the entity's frame is not 0,
5777 // and only if the texture has an alternate animation
5778 if (rsurface.ent_alttextures && t->anim_total[1])
5779 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5781 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5783 texture->currentframe = t;
5786 // update currentskinframe to be a qw skin or animation frame
5787 if (rsurface.ent_qwskin >= 0)
5789 i = rsurface.ent_qwskin;
5790 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5792 r_qwskincache_size = cl.maxclients;
5794 Mem_Free(r_qwskincache);
5795 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5797 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5798 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5799 t->currentskinframe = r_qwskincache[i].skinframe;
5800 if (t->currentskinframe == NULL)
5801 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5803 else if (t->numskinframes >= 2)
5804 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5805 if (t->backgroundnumskinframes >= 2)
5806 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5808 t->currentmaterialflags = t->basematerialflags;
5809 t->currentalpha = rsurface.ent_color[3];
5810 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5811 t->currentalpha *= r_wateralpha.value;
5812 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5813 t->currentalpha *= t->r_water_wateralpha;
5814 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5815 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5816 if (!(rsurface.ent_flags & RENDER_LIGHT))
5817 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5818 else if (rsurface.modeltexcoordlightmap2f == NULL)
5820 // pick a model lighting mode
5821 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5822 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5824 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5826 if (rsurface.ent_flags & RENDER_ADDITIVE)
5827 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5828 else if (t->currentalpha < 1)
5829 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5830 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5831 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5832 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5833 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5834 if (t->backgroundnumskinframes)
5835 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5836 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5838 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5839 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5842 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5844 // there is no tcmod
5845 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5847 t->currenttexmatrix = r_waterscrollmatrix;
5848 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5850 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
5852 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5853 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5856 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5857 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5858 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5859 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5861 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5862 if (t->currentskinframe->qpixels)
5863 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
5864 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5865 t->glosstexture = r_texture_black;
5866 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5867 t->backgroundglosstexture = r_texture_black;
5868 t->specularpower = r_shadow_glossexponent.value;
5869 // TODO: store reference values for these in the texture?
5870 t->specularscale = 0;
5871 if (r_shadow_gloss.integer > 0)
5873 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5875 if (r_shadow_glossintensity.value > 0)
5877 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5878 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5879 t->specularscale = r_shadow_glossintensity.value;
5882 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5884 t->glosstexture = r_texture_white;
5885 t->backgroundglosstexture = r_texture_white;
5886 t->specularscale = r_shadow_gloss2intensity.value;
5887 t->specularpower = r_shadow_gloss2exponent.value;
5890 t->specularscale *= t->specularscalemod;
5891 t->specularpower *= t->specularpowermod;
5893 // lightmaps mode looks bad with dlights using actual texturing, so turn
5894 // off the colormap and glossmap, but leave the normalmap on as it still
5895 // accurately represents the shading involved
5896 if (gl_lightmaps.integer)
5898 t->basetexture = r_texture_grey128;
5899 t->backgroundbasetexture = NULL;
5900 t->specularscale = 0;
5901 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5904 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5905 VectorClear(t->dlightcolor);
5906 t->currentnumlayers = 0;
5907 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5910 int blendfunc1, blendfunc2;
5912 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5914 blendfunc1 = GL_SRC_ALPHA;
5915 blendfunc2 = GL_ONE;
5917 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5919 blendfunc1 = GL_SRC_ALPHA;
5920 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5922 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5924 blendfunc1 = t->customblendfunc[0];
5925 blendfunc2 = t->customblendfunc[1];
5929 blendfunc1 = GL_ONE;
5930 blendfunc2 = GL_ZERO;
5932 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5933 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5934 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5935 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5937 // fullbright is not affected by r_refdef.lightmapintensity
5938 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]);
5939 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5940 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]);
5941 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5942 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]);
5946 vec3_t ambientcolor;
5948 // set the color tint used for lights affecting this surface
5949 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5951 // q3bsp has no lightmap updates, so the lightstylevalue that
5952 // would normally be baked into the lightmap must be
5953 // applied to the color
5954 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5955 if (model->type == mod_brushq3)
5956 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5957 colorscale *= r_refdef.lightmapintensity;
5958 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5959 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5960 // basic lit geometry
5961 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]);
5962 // add pants/shirt if needed
5963 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5964 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]);
5965 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5966 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]);
5967 // now add ambient passes if needed
5968 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5970 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]);
5971 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5972 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]);
5973 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5974 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]);
5977 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5978 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]);
5979 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5981 // if this is opaque use alpha blend which will darken the earlier
5984 // if this is an alpha blended material, all the earlier passes
5985 // were darkened by fog already, so we only need to add the fog
5986 // color ontop through the fog mask texture
5988 // if this is an additive blended material, all the earlier passes
5989 // were darkened by fog already, and we should not add fog color
5990 // (because the background was not darkened, there is no fog color
5991 // that was lost behind it).
5992 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]);
5996 return t->currentframe;
5999 rsurfacestate_t rsurface;
6001 void R_Mesh_ResizeArrays(int newvertices)
6004 if (rsurface.array_size >= newvertices)
6006 if (rsurface.array_modelvertex3f)
6007 Mem_Free(rsurface.array_modelvertex3f);
6008 rsurface.array_size = (newvertices + 1023) & ~1023;
6009 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
6010 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
6011 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
6012 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
6013 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
6014 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
6015 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
6016 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
6017 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
6018 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
6019 rsurface.array_color4f = base + rsurface.array_size * 27;
6020 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6023 void RSurf_ActiveWorldEntity(void)
6025 dp_model_t *model = r_refdef.scene.worldmodel;
6026 //if (rsurface.entity == r_refdef.scene.worldentity)
6028 rsurface.entity = r_refdef.scene.worldentity;
6029 rsurface.skeleton = NULL;
6030 rsurface.ent_skinnum = 0;
6031 rsurface.ent_qwskin = -1;
6032 rsurface.ent_shadertime = 0;
6033 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
6034 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6035 if (rsurface.array_size < model->surfmesh.num_vertices)
6036 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6037 rsurface.matrix = identitymatrix;
6038 rsurface.inversematrix = identitymatrix;
6039 rsurface.matrixscale = 1;
6040 rsurface.inversematrixscale = 1;
6041 R_Mesh_Matrix(&identitymatrix);
6042 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6043 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6044 rsurface.fograngerecip = r_refdef.fograngerecip;
6045 rsurface.fogheightfade = r_refdef.fogheightfade;
6046 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6047 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6048 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6049 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6050 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6051 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6052 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6053 VectorSet(rsurface.glowmod, 1, 1, 1);
6054 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6055 rsurface.frameblend[0].lerp = 1;
6056 rsurface.ent_alttextures = false;
6057 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6058 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6059 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6060 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6061 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6062 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6063 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6064 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6065 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6066 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6067 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6068 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6069 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6070 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6071 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6072 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6073 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6074 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6075 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6076 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6077 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6078 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6079 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6080 rsurface.modelelement3i = model->surfmesh.data_element3i;
6081 rsurface.modelelement3s = model->surfmesh.data_element3s;
6082 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6083 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6084 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6085 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6086 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6087 rsurface.modelsurfaces = model->data_surfaces;
6088 rsurface.generatedvertex = false;
6089 rsurface.vertex3f = rsurface.modelvertex3f;
6090 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6091 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6092 rsurface.svector3f = rsurface.modelsvector3f;
6093 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6094 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6095 rsurface.tvector3f = rsurface.modeltvector3f;
6096 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6097 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6098 rsurface.normal3f = rsurface.modelnormal3f;
6099 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6100 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6101 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6104 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6106 dp_model_t *model = ent->model;
6107 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6109 rsurface.entity = (entity_render_t *)ent;
6110 rsurface.skeleton = ent->skeleton;
6111 rsurface.ent_skinnum = ent->skinnum;
6112 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;
6113 rsurface.ent_shadertime = ent->shadertime;
6114 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6115 rsurface.ent_flags = ent->flags;
6116 if (rsurface.array_size < model->surfmesh.num_vertices)
6117 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6118 rsurface.matrix = ent->matrix;
6119 rsurface.inversematrix = ent->inversematrix;
6120 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6121 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6122 R_Mesh_Matrix(&rsurface.matrix);
6123 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6124 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6125 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6126 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6127 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6128 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6129 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6130 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6131 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6132 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6133 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6134 VectorCopy(ent->glowmod, rsurface.glowmod);
6135 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6136 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6137 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6138 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6139 if (ent->model->brush.submodel)
6141 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6142 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6144 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6146 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6148 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6149 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6150 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6151 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6153 else if (wanttangents)
6155 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6156 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6157 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6158 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6159 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6161 else if (wantnormals)
6163 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6164 rsurface.modelsvector3f = NULL;
6165 rsurface.modeltvector3f = NULL;
6166 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6167 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6171 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6172 rsurface.modelsvector3f = NULL;
6173 rsurface.modeltvector3f = NULL;
6174 rsurface.modelnormal3f = NULL;
6175 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6177 rsurface.modelvertex3f_bufferobject = 0;
6178 rsurface.modelvertex3f_bufferoffset = 0;
6179 rsurface.modelsvector3f_bufferobject = 0;
6180 rsurface.modelsvector3f_bufferoffset = 0;
6181 rsurface.modeltvector3f_bufferobject = 0;
6182 rsurface.modeltvector3f_bufferoffset = 0;
6183 rsurface.modelnormal3f_bufferobject = 0;
6184 rsurface.modelnormal3f_bufferoffset = 0;
6185 rsurface.generatedvertex = true;
6189 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6190 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6191 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6192 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6193 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6194 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6195 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6196 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6197 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6198 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6199 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6200 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6201 rsurface.generatedvertex = false;
6203 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6204 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6205 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6206 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6207 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6208 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6209 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6210 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6211 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6212 rsurface.modelelement3i = model->surfmesh.data_element3i;
6213 rsurface.modelelement3s = model->surfmesh.data_element3s;
6214 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6215 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6216 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6217 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6218 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6219 rsurface.modelsurfaces = model->data_surfaces;
6220 rsurface.vertex3f = rsurface.modelvertex3f;
6221 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6222 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6223 rsurface.svector3f = rsurface.modelsvector3f;
6224 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6225 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6226 rsurface.tvector3f = rsurface.modeltvector3f;
6227 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6228 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6229 rsurface.normal3f = rsurface.modelnormal3f;
6230 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6231 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6232 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6235 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)
6237 rsurface.entity = r_refdef.scene.worldentity;
6238 rsurface.skeleton = NULL;
6239 rsurface.ent_skinnum = 0;
6240 rsurface.ent_qwskin = -1;
6241 rsurface.ent_shadertime = shadertime;
6242 Vector4Set(rsurface.ent_color, r, g, b, a);
6243 rsurface.ent_flags = entflags;
6244 rsurface.modelnum_vertices = numvertices;
6245 rsurface.modelnum_triangles = numtriangles;
6246 if (rsurface.array_size < rsurface.modelnum_vertices)
6247 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6248 rsurface.matrix = *matrix;
6249 rsurface.inversematrix = *inversematrix;
6250 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6251 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6252 R_Mesh_Matrix(&rsurface.matrix);
6253 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6254 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6255 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6256 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6257 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6258 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6259 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6260 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6261 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6262 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6263 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6264 VectorSet(rsurface.glowmod, 1, 1, 1);
6265 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6266 rsurface.frameblend[0].lerp = 1;
6267 rsurface.ent_alttextures = false;
6268 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6269 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6272 rsurface.modelvertex3f = vertex3f;
6273 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6274 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6275 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6277 else if (wantnormals)
6279 rsurface.modelvertex3f = vertex3f;
6280 rsurface.modelsvector3f = NULL;
6281 rsurface.modeltvector3f = NULL;
6282 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6286 rsurface.modelvertex3f = vertex3f;
6287 rsurface.modelsvector3f = NULL;
6288 rsurface.modeltvector3f = NULL;
6289 rsurface.modelnormal3f = NULL;
6291 rsurface.modelvertex3f_bufferobject = 0;
6292 rsurface.modelvertex3f_bufferoffset = 0;
6293 rsurface.modelsvector3f_bufferobject = 0;
6294 rsurface.modelsvector3f_bufferoffset = 0;
6295 rsurface.modeltvector3f_bufferobject = 0;
6296 rsurface.modeltvector3f_bufferoffset = 0;
6297 rsurface.modelnormal3f_bufferobject = 0;
6298 rsurface.modelnormal3f_bufferoffset = 0;
6299 rsurface.generatedvertex = true;
6300 rsurface.modellightmapcolor4f = color4f;
6301 rsurface.modellightmapcolor4f_bufferobject = 0;
6302 rsurface.modellightmapcolor4f_bufferoffset = 0;
6303 rsurface.modeltexcoordtexture2f = texcoord2f;
6304 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6305 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6306 rsurface.modeltexcoordlightmap2f = NULL;
6307 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6308 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6309 rsurface.modelelement3i = element3i;
6310 rsurface.modelelement3s = element3s;
6311 rsurface.modelelement3i_bufferobject = 0;
6312 rsurface.modelelement3s_bufferobject = 0;
6313 rsurface.modellightmapoffsets = NULL;
6314 rsurface.modelsurfaces = NULL;
6315 rsurface.vertex3f = rsurface.modelvertex3f;
6316 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6317 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6318 rsurface.svector3f = rsurface.modelsvector3f;
6319 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6320 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6321 rsurface.tvector3f = rsurface.modeltvector3f;
6322 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6323 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6324 rsurface.normal3f = rsurface.modelnormal3f;
6325 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6326 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6327 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6329 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6331 if ((wantnormals || wanttangents) && !normal3f)
6332 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6333 if (wanttangents && !svector3f)
6334 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);
6338 float RSurf_FogPoint(const float *v)
6340 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6341 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6342 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6343 float FogHeightFade = r_refdef.fogheightfade;
6345 unsigned int fogmasktableindex;
6346 if (r_refdef.fogplaneviewabove)
6347 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6349 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6350 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6351 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6354 float RSurf_FogVertex(const float *v)
6356 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6357 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6358 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6359 float FogHeightFade = rsurface.fogheightfade;
6361 unsigned int fogmasktableindex;
6362 if (r_refdef.fogplaneviewabove)
6363 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6365 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6366 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6367 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6370 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6371 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6374 int texturesurfaceindex;
6379 const float *v1, *in_tc;
6381 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6383 q3shaderinfo_deform_t *deform;
6384 // 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
6385 if (rsurface.generatedvertex)
6387 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6388 generatenormals = true;
6389 for (i = 0;i < Q3MAXDEFORMS;i++)
6391 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6393 generatetangents = true;
6394 generatenormals = true;
6396 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6397 generatenormals = true;
6399 if (generatenormals && !rsurface.modelnormal3f)
6401 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6402 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6403 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6404 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6406 if (generatetangents && !rsurface.modelsvector3f)
6408 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6409 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6410 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6411 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6412 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6413 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6414 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);
6417 rsurface.vertex3f = rsurface.modelvertex3f;
6418 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6419 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6420 rsurface.svector3f = rsurface.modelsvector3f;
6421 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6422 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6423 rsurface.tvector3f = rsurface.modeltvector3f;
6424 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6425 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6426 rsurface.normal3f = rsurface.modelnormal3f;
6427 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6428 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6429 // if vertices are deformed (sprite flares and things in maps, possibly
6430 // water waves, bulges and other deformations), generate them into
6431 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6432 // (may be static model data or generated data for an animated model, or
6433 // the previous deform pass)
6434 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6436 switch (deform->deform)
6439 case Q3DEFORM_PROJECTIONSHADOW:
6440 case Q3DEFORM_TEXT0:
6441 case Q3DEFORM_TEXT1:
6442 case Q3DEFORM_TEXT2:
6443 case Q3DEFORM_TEXT3:
6444 case Q3DEFORM_TEXT4:
6445 case Q3DEFORM_TEXT5:
6446 case Q3DEFORM_TEXT6:
6447 case Q3DEFORM_TEXT7:
6450 case Q3DEFORM_AUTOSPRITE:
6451 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6452 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6453 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6454 VectorNormalize(newforward);
6455 VectorNormalize(newright);
6456 VectorNormalize(newup);
6457 // make deformed versions of only the model vertices used by the specified surfaces
6458 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6460 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6461 // a single autosprite surface can contain multiple sprites...
6462 for (j = 0;j < surface->num_vertices - 3;j += 4)
6464 VectorClear(center);
6465 for (i = 0;i < 4;i++)
6466 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6467 VectorScale(center, 0.25f, center);
6468 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6469 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6470 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6471 for (i = 0;i < 4;i++)
6473 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6474 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6477 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);
6478 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);
6480 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6481 rsurface.vertex3f_bufferobject = 0;
6482 rsurface.vertex3f_bufferoffset = 0;
6483 rsurface.svector3f = rsurface.array_deformedsvector3f;
6484 rsurface.svector3f_bufferobject = 0;
6485 rsurface.svector3f_bufferoffset = 0;
6486 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6487 rsurface.tvector3f_bufferobject = 0;
6488 rsurface.tvector3f_bufferoffset = 0;
6489 rsurface.normal3f = rsurface.array_deformednormal3f;
6490 rsurface.normal3f_bufferobject = 0;
6491 rsurface.normal3f_bufferoffset = 0;
6493 case Q3DEFORM_AUTOSPRITE2:
6494 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6495 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6496 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6497 VectorNormalize(newforward);
6498 VectorNormalize(newright);
6499 VectorNormalize(newup);
6500 // make deformed versions of only the model vertices used by the specified surfaces
6501 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6503 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6504 const float *v1, *v2;
6514 memset(shortest, 0, sizeof(shortest));
6515 // a single autosprite surface can contain multiple sprites...
6516 for (j = 0;j < surface->num_vertices - 3;j += 4)
6518 VectorClear(center);
6519 for (i = 0;i < 4;i++)
6520 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6521 VectorScale(center, 0.25f, center);
6522 // find the two shortest edges, then use them to define the
6523 // axis vectors for rotating around the central axis
6524 for (i = 0;i < 6;i++)
6526 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6527 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6529 Debug_PolygonBegin(NULL, 0);
6530 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6531 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);
6532 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6535 l = VectorDistance2(v1, v2);
6536 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6538 l += (1.0f / 1024.0f);
6539 if (shortest[0].length2 > l || i == 0)
6541 shortest[1] = shortest[0];
6542 shortest[0].length2 = l;
6543 shortest[0].v1 = v1;
6544 shortest[0].v2 = v2;
6546 else if (shortest[1].length2 > l || i == 1)
6548 shortest[1].length2 = l;
6549 shortest[1].v1 = v1;
6550 shortest[1].v2 = v2;
6553 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6554 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6556 Debug_PolygonBegin(NULL, 0);
6557 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6558 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);
6559 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6562 // this calculates the right vector from the shortest edge
6563 // and the up vector from the edge midpoints
6564 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6565 VectorNormalize(right);
6566 VectorSubtract(end, start, up);
6567 VectorNormalize(up);
6568 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6569 VectorSubtract(rsurface.localvieworigin, center, forward);
6570 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6571 VectorNegate(forward, forward);
6572 VectorReflect(forward, 0, up, forward);
6573 VectorNormalize(forward);
6574 CrossProduct(up, forward, newright);
6575 VectorNormalize(newright);
6577 Debug_PolygonBegin(NULL, 0);
6578 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);
6579 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[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);
6584 Debug_PolygonBegin(NULL, 0);
6585 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6586 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6587 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6590 // rotate the quad around the up axis vector, this is made
6591 // especially easy by the fact we know the quad is flat,
6592 // so we only have to subtract the center position and
6593 // measure distance along the right vector, and then
6594 // multiply that by the newright vector and add back the
6596 // we also need to subtract the old position to undo the
6597 // displacement from the center, which we do with a
6598 // DotProduct, the subtraction/addition of center is also
6599 // optimized into DotProducts here
6600 l = DotProduct(right, center);
6601 for (i = 0;i < 4;i++)
6603 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6604 f = DotProduct(right, v1) - l;
6605 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6608 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);
6609 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);
6611 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6612 rsurface.vertex3f_bufferobject = 0;
6613 rsurface.vertex3f_bufferoffset = 0;
6614 rsurface.svector3f = rsurface.array_deformedsvector3f;
6615 rsurface.svector3f_bufferobject = 0;
6616 rsurface.svector3f_bufferoffset = 0;
6617 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6618 rsurface.tvector3f_bufferobject = 0;
6619 rsurface.tvector3f_bufferoffset = 0;
6620 rsurface.normal3f = rsurface.array_deformednormal3f;
6621 rsurface.normal3f_bufferobject = 0;
6622 rsurface.normal3f_bufferoffset = 0;
6624 case Q3DEFORM_NORMAL:
6625 // deform the normals to make reflections wavey
6626 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6628 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6629 for (j = 0;j < surface->num_vertices;j++)
6632 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6633 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6634 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6635 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6636 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6637 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6638 VectorNormalize(normal);
6640 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);
6642 rsurface.svector3f = rsurface.array_deformedsvector3f;
6643 rsurface.svector3f_bufferobject = 0;
6644 rsurface.svector3f_bufferoffset = 0;
6645 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6646 rsurface.tvector3f_bufferobject = 0;
6647 rsurface.tvector3f_bufferoffset = 0;
6648 rsurface.normal3f = rsurface.array_deformednormal3f;
6649 rsurface.normal3f_bufferobject = 0;
6650 rsurface.normal3f_bufferoffset = 0;
6653 // deform vertex array to make wavey water and flags and such
6654 waveparms[0] = deform->waveparms[0];
6655 waveparms[1] = deform->waveparms[1];
6656 waveparms[2] = deform->waveparms[2];
6657 waveparms[3] = deform->waveparms[3];
6658 // this is how a divisor of vertex influence on deformation
6659 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6660 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6661 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6663 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6664 for (j = 0;j < surface->num_vertices;j++)
6666 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6667 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6668 // if the wavefunc depends on time, evaluate it per-vertex
6671 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6672 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6674 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6677 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6678 rsurface.vertex3f_bufferobject = 0;
6679 rsurface.vertex3f_bufferoffset = 0;
6681 case Q3DEFORM_BULGE:
6682 // deform vertex array to make the surface have moving bulges
6683 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6685 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6686 for (j = 0;j < surface->num_vertices;j++)
6688 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6689 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6692 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6693 rsurface.vertex3f_bufferobject = 0;
6694 rsurface.vertex3f_bufferoffset = 0;
6697 // deform vertex array
6698 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6699 VectorScale(deform->parms, scale, waveparms);
6700 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6702 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6703 for (j = 0;j < surface->num_vertices;j++)
6704 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6706 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6707 rsurface.vertex3f_bufferobject = 0;
6708 rsurface.vertex3f_bufferoffset = 0;
6712 // generate texcoords based on the chosen texcoord source
6713 switch(rsurface.texture->tcgen.tcgen)
6716 case Q3TCGEN_TEXTURE:
6717 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6718 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6719 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6721 case Q3TCGEN_LIGHTMAP:
6722 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6723 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6724 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6726 case Q3TCGEN_VECTOR:
6727 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6729 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6730 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)
6732 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6733 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6736 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6737 rsurface.texcoordtexture2f_bufferobject = 0;
6738 rsurface.texcoordtexture2f_bufferoffset = 0;
6740 case Q3TCGEN_ENVIRONMENT:
6741 // make environment reflections using a spheremap
6742 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6744 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6745 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6746 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6747 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6748 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6750 // identical to Q3A's method, but executed in worldspace so
6751 // carried models can be shiny too
6753 float viewer[3], d, reflected[3], worldreflected[3];
6755 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6756 // VectorNormalize(viewer);
6758 d = DotProduct(normal, viewer);
6760 reflected[0] = normal[0]*2*d - viewer[0];
6761 reflected[1] = normal[1]*2*d - viewer[1];
6762 reflected[2] = normal[2]*2*d - viewer[2];
6763 // note: this is proportinal to viewer, so we can normalize later
6765 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6766 VectorNormalize(worldreflected);
6768 // note: this sphere map only uses world x and z!
6769 // so positive and negative y will LOOK THE SAME.
6770 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6771 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6774 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6775 rsurface.texcoordtexture2f_bufferobject = 0;
6776 rsurface.texcoordtexture2f_bufferoffset = 0;
6779 // the only tcmod that needs software vertex processing is turbulent, so
6780 // check for it here and apply the changes if needed
6781 // and we only support that as the first one
6782 // (handling a mixture of turbulent and other tcmods would be problematic
6783 // without punting it entirely to a software path)
6784 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6786 amplitude = rsurface.texture->tcmods[0].parms[1];
6787 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6788 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6790 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6791 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)
6793 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6794 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6797 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6798 rsurface.texcoordtexture2f_bufferobject = 0;
6799 rsurface.texcoordtexture2f_bufferoffset = 0;
6801 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6802 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6803 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6804 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6807 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6810 const msurface_t *surface = texturesurfacelist[0];
6811 const msurface_t *surface2;
6816 // TODO: lock all array ranges before render, rather than on each surface
6817 if (texturenumsurfaces == 1)
6819 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6820 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);
6822 else if (r_batchmode.integer == 2)
6824 #define MAXBATCHTRIANGLES 4096
6825 int batchtriangles = 0;
6826 int batchelements[MAXBATCHTRIANGLES*3];
6827 for (i = 0;i < texturenumsurfaces;i = j)
6829 surface = texturesurfacelist[i];
6831 if (surface->num_triangles > MAXBATCHTRIANGLES)
6833 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);
6836 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6837 batchtriangles = surface->num_triangles;
6838 firstvertex = surface->num_firstvertex;
6839 endvertex = surface->num_firstvertex + surface->num_vertices;
6840 for (;j < texturenumsurfaces;j++)
6842 surface2 = texturesurfacelist[j];
6843 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6845 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6846 batchtriangles += surface2->num_triangles;
6847 firstvertex = min(firstvertex, surface2->num_firstvertex);
6848 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6850 surface2 = texturesurfacelist[j-1];
6851 numvertices = endvertex - firstvertex;
6852 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6855 else if (r_batchmode.integer == 1)
6857 for (i = 0;i < texturenumsurfaces;i = j)
6859 surface = texturesurfacelist[i];
6860 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6861 if (texturesurfacelist[j] != surface2)
6863 surface2 = texturesurfacelist[j-1];
6864 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6865 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6866 GL_LockArrays(surface->num_firstvertex, numvertices);
6867 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6872 for (i = 0;i < texturenumsurfaces;i++)
6874 surface = texturesurfacelist[i];
6875 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6876 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);
6881 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6883 int i, planeindex, vertexindex;
6887 r_waterstate_waterplane_t *p, *bestp;
6888 const msurface_t *surface;
6889 if (r_waterstate.renderingscene)
6891 for (i = 0;i < texturenumsurfaces;i++)
6893 surface = texturesurfacelist[i];
6894 if (lightmaptexunit >= 0)
6895 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6896 if (deluxemaptexunit >= 0)
6897 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6898 // pick the closest matching water plane
6901 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6904 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6906 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6907 d += fabs(PlaneDiff(vert, &p->plane));
6909 if (bestd > d || !bestp)
6917 if (refractiontexunit >= 0)
6918 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6919 if (reflectiontexunit >= 0)
6920 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6924 if (refractiontexunit >= 0)
6925 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6926 if (reflectiontexunit >= 0)
6927 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6929 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6930 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);
6934 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6938 const msurface_t *surface = texturesurfacelist[0];
6939 const msurface_t *surface2;
6944 // TODO: lock all array ranges before render, rather than on each surface
6945 if (texturenumsurfaces == 1)
6947 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6948 if (deluxemaptexunit >= 0)
6949 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6950 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6951 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);
6953 else if (r_batchmode.integer == 2)
6955 #define MAXBATCHTRIANGLES 4096
6956 int batchtriangles = 0;
6957 int batchelements[MAXBATCHTRIANGLES*3];
6958 for (i = 0;i < texturenumsurfaces;i = j)
6960 surface = texturesurfacelist[i];
6961 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6962 if (deluxemaptexunit >= 0)
6963 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6965 if (surface->num_triangles > MAXBATCHTRIANGLES)
6967 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);
6970 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6971 batchtriangles = surface->num_triangles;
6972 firstvertex = surface->num_firstvertex;
6973 endvertex = surface->num_firstvertex + surface->num_vertices;
6974 for (;j < texturenumsurfaces;j++)
6976 surface2 = texturesurfacelist[j];
6977 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6979 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6980 batchtriangles += surface2->num_triangles;
6981 firstvertex = min(firstvertex, surface2->num_firstvertex);
6982 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6984 surface2 = texturesurfacelist[j-1];
6985 numvertices = endvertex - firstvertex;
6986 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6989 else if (r_batchmode.integer == 1)
6992 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6993 for (i = 0;i < texturenumsurfaces;i = j)
6995 surface = texturesurfacelist[i];
6996 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6997 if (texturesurfacelist[j] != surface2)
6999 Con_Printf(" %i", j - i);
7002 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
7004 for (i = 0;i < texturenumsurfaces;i = j)
7006 surface = texturesurfacelist[i];
7007 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7008 if (deluxemaptexunit >= 0)
7009 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7010 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7011 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
7014 Con_Printf(" %i", j - i);
7016 surface2 = texturesurfacelist[j-1];
7017 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7018 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7019 GL_LockArrays(surface->num_firstvertex, numvertices);
7020 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7028 for (i = 0;i < texturenumsurfaces;i++)
7030 surface = texturesurfacelist[i];
7031 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7032 if (deluxemaptexunit >= 0)
7033 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7034 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7035 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);
7040 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7043 int texturesurfaceindex;
7044 if (r_showsurfaces.integer == 2)
7046 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7048 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7049 for (j = 0;j < surface->num_triangles;j++)
7051 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7052 GL_Color(f, f, f, 1);
7053 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7059 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7061 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7062 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7063 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);
7064 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7065 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);
7070 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7072 int texturesurfaceindex;
7076 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7078 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7079 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)
7087 rsurface.lightmapcolor4f = rsurface.array_color4f;
7088 rsurface.lightmapcolor4f_bufferobject = 0;
7089 rsurface.lightmapcolor4f_bufferoffset = 0;
7092 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7094 int texturesurfaceindex;
7100 if (rsurface.lightmapcolor4f)
7102 // generate color arrays for the surfaces in this list
7103 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7105 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7106 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
7108 f = RSurf_FogVertex(v);
7118 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7120 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7121 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)
7123 f = RSurf_FogVertex(v);
7131 rsurface.lightmapcolor4f = rsurface.array_color4f;
7132 rsurface.lightmapcolor4f_bufferobject = 0;
7133 rsurface.lightmapcolor4f_bufferoffset = 0;
7136 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7138 int texturesurfaceindex;
7144 if (!rsurface.lightmapcolor4f)
7146 // generate color arrays for the surfaces in this list
7147 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7149 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7150 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)
7152 f = RSurf_FogVertex(v);
7153 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7154 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7155 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7159 rsurface.lightmapcolor4f = rsurface.array_color4f;
7160 rsurface.lightmapcolor4f_bufferobject = 0;
7161 rsurface.lightmapcolor4f_bufferoffset = 0;
7164 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7166 int texturesurfaceindex;
7170 if (!rsurface.lightmapcolor4f)
7172 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7174 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7175 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)
7183 rsurface.lightmapcolor4f = rsurface.array_color4f;
7184 rsurface.lightmapcolor4f_bufferobject = 0;
7185 rsurface.lightmapcolor4f_bufferoffset = 0;
7188 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7190 int texturesurfaceindex;
7194 if (!rsurface.lightmapcolor4f)
7196 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7198 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7199 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)
7201 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7202 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7203 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7207 rsurface.lightmapcolor4f = rsurface.array_color4f;
7208 rsurface.lightmapcolor4f_bufferobject = 0;
7209 rsurface.lightmapcolor4f_bufferoffset = 0;
7212 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7215 rsurface.lightmapcolor4f = NULL;
7216 rsurface.lightmapcolor4f_bufferobject = 0;
7217 rsurface.lightmapcolor4f_bufferoffset = 0;
7218 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7219 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7220 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7221 GL_Color(r, g, b, a);
7222 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7225 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7227 // TODO: optimize applyfog && applycolor case
7228 // just apply fog if necessary, and tint the fog color array if necessary
7229 rsurface.lightmapcolor4f = NULL;
7230 rsurface.lightmapcolor4f_bufferobject = 0;
7231 rsurface.lightmapcolor4f_bufferoffset = 0;
7232 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7233 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7234 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7235 GL_Color(r, g, b, a);
7236 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7239 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7241 int texturesurfaceindex;
7245 if (texturesurfacelist[0]->lightmapinfo)
7247 // generate color arrays for the surfaces in this list
7248 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7250 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7251 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7253 if (surface->lightmapinfo->samples)
7255 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7256 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7257 VectorScale(lm, scale, c);
7258 if (surface->lightmapinfo->styles[1] != 255)
7260 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7262 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7263 VectorMA(c, scale, lm, c);
7264 if (surface->lightmapinfo->styles[2] != 255)
7267 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7268 VectorMA(c, scale, lm, c);
7269 if (surface->lightmapinfo->styles[3] != 255)
7272 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7273 VectorMA(c, scale, lm, c);
7283 rsurface.lightmapcolor4f = rsurface.array_color4f;
7284 rsurface.lightmapcolor4f_bufferobject = 0;
7285 rsurface.lightmapcolor4f_bufferoffset = 0;
7289 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7290 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7291 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7293 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7294 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7295 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7296 GL_Color(r, g, b, a);
7297 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7300 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7302 int texturesurfaceindex;
7309 vec3_t ambientcolor;
7310 vec3_t diffusecolor;
7314 VectorCopy(rsurface.modellight_lightdir, lightdir);
7315 f = 0.5f * r_refdef.lightmapintensity;
7316 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7317 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7318 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7319 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7320 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7321 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7323 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7325 // generate color arrays for the surfaces in this list
7326 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7328 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7329 int numverts = surface->num_vertices;
7330 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7331 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7332 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7333 // q3-style directional shading
7334 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7336 if ((f = DotProduct(n, lightdir)) > 0)
7337 VectorMA(ambientcolor, f, diffusecolor, c);
7339 VectorCopy(ambientcolor, c);
7347 rsurface.lightmapcolor4f = rsurface.array_color4f;
7348 rsurface.lightmapcolor4f_bufferobject = 0;
7349 rsurface.lightmapcolor4f_bufferoffset = 0;
7350 *applycolor = false;
7354 *r = ambientcolor[0];
7355 *g = ambientcolor[1];
7356 *b = ambientcolor[2];
7357 rsurface.lightmapcolor4f = NULL;
7358 rsurface.lightmapcolor4f_bufferobject = 0;
7359 rsurface.lightmapcolor4f_bufferoffset = 0;
7363 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7365 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7366 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7367 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7368 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7369 GL_Color(r, g, b, a);
7370 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7373 void RSurf_SetupDepthAndCulling(void)
7375 // submodels are biased to avoid z-fighting with world surfaces that they
7376 // may be exactly overlapping (avoids z-fighting artifacts on certain
7377 // doors and things in Quake maps)
7378 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7379 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7380 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7381 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7384 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7386 // transparent sky would be ridiculous
7387 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7389 R_SetupGenericShader(false);
7390 skyrenderlater = true;
7391 RSurf_SetupDepthAndCulling();
7393 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7394 // skymasking on them, and Quake3 never did sky masking (unlike
7395 // software Quake and software Quake2), so disable the sky masking
7396 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7397 // and skymasking also looks very bad when noclipping outside the
7398 // level, so don't use it then either.
7399 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7401 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7402 R_Mesh_ColorPointer(NULL, 0, 0);
7403 R_Mesh_ResetTextureState();
7404 if (skyrendermasked)
7406 R_SetupDepthOrShadowShader();
7407 // depth-only (masking)
7408 GL_ColorMask(0,0,0,0);
7409 // just to make sure that braindead drivers don't draw
7410 // anything despite that colormask...
7411 GL_BlendFunc(GL_ZERO, GL_ONE);
7415 R_SetupGenericShader(false);
7417 GL_BlendFunc(GL_ONE, GL_ZERO);
7419 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7420 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7421 if (skyrendermasked)
7422 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7424 R_Mesh_ResetTextureState();
7425 GL_Color(1, 1, 1, 1);
7428 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7430 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7433 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7434 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7435 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7436 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7437 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7438 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7439 if (rsurface.texture->backgroundcurrentskinframe)
7441 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7442 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7443 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7444 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7446 if(rsurface.texture->colormapping)
7448 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7449 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7451 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7452 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7453 R_Mesh_ColorPointer(NULL, 0, 0);
7455 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7457 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7459 // render background
7460 GL_BlendFunc(GL_ONE, GL_ZERO);
7462 GL_AlphaTest(false);
7464 GL_Color(1, 1, 1, 1);
7465 R_Mesh_ColorPointer(NULL, 0, 0);
7467 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7468 if (r_glsl_permutation)
7470 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7471 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7472 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7473 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7474 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7475 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7476 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);
7478 GL_LockArrays(0, 0);
7480 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7481 GL_DepthMask(false);
7482 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7483 R_Mesh_ColorPointer(NULL, 0, 0);
7485 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7486 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7487 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7490 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7491 if (!r_glsl_permutation)
7494 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7495 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7496 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7497 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7498 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7499 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7501 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7503 GL_BlendFunc(GL_ONE, GL_ZERO);
7505 GL_AlphaTest(false);
7509 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7510 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7511 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7514 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7516 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7517 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);
7519 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7523 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7524 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);
7526 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7528 GL_LockArrays(0, 0);
7531 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7533 // OpenGL 1.3 path - anything not completely ancient
7534 int texturesurfaceindex;
7535 qboolean applycolor;
7539 const texturelayer_t *layer;
7540 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7542 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7545 int layertexrgbscale;
7546 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7548 if (layerindex == 0)
7552 GL_AlphaTest(false);
7553 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7556 GL_DepthMask(layer->depthmask && writedepth);
7557 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7558 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7560 layertexrgbscale = 4;
7561 VectorScale(layer->color, 0.25f, layercolor);
7563 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7565 layertexrgbscale = 2;
7566 VectorScale(layer->color, 0.5f, layercolor);
7570 layertexrgbscale = 1;
7571 VectorScale(layer->color, 1.0f, layercolor);
7573 layercolor[3] = layer->color[3];
7574 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7575 R_Mesh_ColorPointer(NULL, 0, 0);
7576 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7577 switch (layer->type)
7579 case TEXTURELAYERTYPE_LITTEXTURE:
7580 memset(&m, 0, sizeof(m));
7581 m.tex[0] = R_GetTexture(r_texture_white);
7582 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7583 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7584 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7585 m.tex[1] = R_GetTexture(layer->texture);
7586 m.texmatrix[1] = layer->texmatrix;
7587 m.texrgbscale[1] = layertexrgbscale;
7588 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7589 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7590 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7591 R_Mesh_TextureState(&m);
7592 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7593 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7594 else if (rsurface.uselightmaptexture)
7595 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7597 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7599 case TEXTURELAYERTYPE_TEXTURE:
7600 memset(&m, 0, sizeof(m));
7601 m.tex[0] = R_GetTexture(layer->texture);
7602 m.texmatrix[0] = layer->texmatrix;
7603 m.texrgbscale[0] = layertexrgbscale;
7604 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7605 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7606 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7607 R_Mesh_TextureState(&m);
7608 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7610 case TEXTURELAYERTYPE_FOG:
7611 memset(&m, 0, sizeof(m));
7612 m.texrgbscale[0] = layertexrgbscale;
7615 m.tex[0] = R_GetTexture(layer->texture);
7616 m.texmatrix[0] = layer->texmatrix;
7617 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7618 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7619 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7621 R_Mesh_TextureState(&m);
7622 // generate a color array for the fog pass
7623 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7624 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7630 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7631 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)
7633 f = 1 - RSurf_FogVertex(v);
7634 c[0] = layercolor[0];
7635 c[1] = layercolor[1];
7636 c[2] = layercolor[2];
7637 c[3] = f * layercolor[3];
7640 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7643 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7645 GL_LockArrays(0, 0);
7648 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7650 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7651 GL_AlphaTest(false);
7655 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7657 // OpenGL 1.1 - crusty old voodoo path
7658 int texturesurfaceindex;
7662 const texturelayer_t *layer;
7663 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7665 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7667 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7669 if (layerindex == 0)
7673 GL_AlphaTest(false);
7674 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7677 GL_DepthMask(layer->depthmask && writedepth);
7678 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7679 R_Mesh_ColorPointer(NULL, 0, 0);
7680 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7681 switch (layer->type)
7683 case TEXTURELAYERTYPE_LITTEXTURE:
7684 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7686 // two-pass lit texture with 2x rgbscale
7687 // first the lightmap pass
7688 memset(&m, 0, sizeof(m));
7689 m.tex[0] = R_GetTexture(r_texture_white);
7690 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7691 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7692 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7693 R_Mesh_TextureState(&m);
7694 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7695 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7696 else if (rsurface.uselightmaptexture)
7697 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7699 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7700 GL_LockArrays(0, 0);
7701 // then apply the texture to it
7702 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7703 memset(&m, 0, sizeof(m));
7704 m.tex[0] = R_GetTexture(layer->texture);
7705 m.texmatrix[0] = layer->texmatrix;
7706 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7707 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7708 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7709 R_Mesh_TextureState(&m);
7710 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);
7714 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7715 memset(&m, 0, sizeof(m));
7716 m.tex[0] = R_GetTexture(layer->texture);
7717 m.texmatrix[0] = layer->texmatrix;
7718 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7719 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7720 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7721 R_Mesh_TextureState(&m);
7722 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7723 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);
7725 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);
7728 case TEXTURELAYERTYPE_TEXTURE:
7729 // singletexture unlit texture with transparency support
7730 memset(&m, 0, sizeof(m));
7731 m.tex[0] = R_GetTexture(layer->texture);
7732 m.texmatrix[0] = layer->texmatrix;
7733 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7734 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7735 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7736 R_Mesh_TextureState(&m);
7737 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);
7739 case TEXTURELAYERTYPE_FOG:
7740 // singletexture fogging
7741 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7744 memset(&m, 0, sizeof(m));
7745 m.tex[0] = R_GetTexture(layer->texture);
7746 m.texmatrix[0] = layer->texmatrix;
7747 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7748 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7749 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7750 R_Mesh_TextureState(&m);
7753 R_Mesh_ResetTextureState();
7754 // generate a color array for the fog pass
7755 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7761 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7762 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)
7764 f = 1 - RSurf_FogVertex(v);
7765 c[0] = layer->color[0];
7766 c[1] = layer->color[1];
7767 c[2] = layer->color[2];
7768 c[3] = f * layer->color[3];
7771 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7774 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7776 GL_LockArrays(0, 0);
7779 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7781 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7782 GL_AlphaTest(false);
7786 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7790 GL_AlphaTest(false);
7791 R_Mesh_ColorPointer(NULL, 0, 0);
7792 R_Mesh_ResetTextureState();
7793 R_SetupGenericShader(false);
7795 if(rsurface.texture && rsurface.texture->currentskinframe)
7797 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7798 c[3] *= rsurface.texture->currentalpha;
7808 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7810 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7811 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7812 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7815 // brighten it up (as texture value 127 means "unlit")
7816 c[0] *= 2 * r_refdef.view.colorscale;
7817 c[1] *= 2 * r_refdef.view.colorscale;
7818 c[2] *= 2 * r_refdef.view.colorscale;
7820 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7821 c[3] *= r_wateralpha.value;
7823 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7825 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7826 GL_DepthMask(false);
7828 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7830 GL_BlendFunc(GL_ONE, GL_ONE);
7831 GL_DepthMask(false);
7833 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7835 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7836 GL_DepthMask(false);
7838 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7840 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7841 GL_DepthMask(false);
7845 GL_BlendFunc(GL_ONE, GL_ZERO);
7846 GL_DepthMask(writedepth);
7849 rsurface.lightmapcolor4f = NULL;
7851 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7853 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7855 rsurface.lightmapcolor4f = NULL;
7856 rsurface.lightmapcolor4f_bufferobject = 0;
7857 rsurface.lightmapcolor4f_bufferoffset = 0;
7859 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7861 qboolean applycolor = true;
7864 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7866 r_refdef.lightmapintensity = 1;
7867 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7868 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7872 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7874 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7875 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7876 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7879 if(!rsurface.lightmapcolor4f)
7880 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7882 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7883 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7884 if(r_refdef.fogenabled)
7885 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7887 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7888 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7891 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7894 RSurf_SetupDepthAndCulling();
7895 if (r_showsurfaces.integer == 3)
7896 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7897 else if (r_glsl.integer && vid.support.arb_fragment_shader)
7898 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7899 else if (gl_combine.integer && r_textureunits.integer >= 2)
7900 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7902 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7906 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7909 RSurf_SetupDepthAndCulling();
7910 if (r_showsurfaces.integer == 3)
7911 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7912 else if (r_glsl.integer && vid.support.arb_fragment_shader)
7913 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7914 else if (gl_combine.integer && r_textureunits.integer >= 2)
7915 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7917 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7921 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7924 int texturenumsurfaces, endsurface;
7926 const msurface_t *surface;
7927 const msurface_t *texturesurfacelist[1024];
7929 // if the model is static it doesn't matter what value we give for
7930 // wantnormals and wanttangents, so this logic uses only rules applicable
7931 // to a model, knowing that they are meaningless otherwise
7932 if (ent == r_refdef.scene.worldentity)
7933 RSurf_ActiveWorldEntity();
7934 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7935 RSurf_ActiveModelEntity(ent, false, false);
7937 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && vid.support.arb_fragment_shader);
7939 for (i = 0;i < numsurfaces;i = j)
7942 surface = rsurface.modelsurfaces + surfacelist[i];
7943 texture = surface->texture;
7944 rsurface.texture = R_GetCurrentTexture(texture);
7945 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7946 // scan ahead until we find a different texture
7947 endsurface = min(i + 1024, numsurfaces);
7948 texturenumsurfaces = 0;
7949 texturesurfacelist[texturenumsurfaces++] = surface;
7950 for (;j < endsurface;j++)
7952 surface = rsurface.modelsurfaces + surfacelist[j];
7953 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7955 texturesurfacelist[texturenumsurfaces++] = surface;
7957 // render the range of surfaces
7958 if (ent == r_refdef.scene.worldentity)
7959 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7961 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7963 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7964 GL_AlphaTest(false);
7967 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7969 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7973 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7975 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7977 RSurf_SetupDepthAndCulling();
7978 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7979 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7981 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7983 RSurf_SetupDepthAndCulling();
7984 GL_AlphaTest(false);
7985 R_Mesh_ColorPointer(NULL, 0, 0);
7986 R_Mesh_ResetTextureState();
7987 R_SetupGenericShader(false);
7988 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7990 GL_BlendFunc(GL_ONE, GL_ZERO);
7991 GL_Color(0, 0, 0, 1);
7992 GL_DepthTest(writedepth);
7993 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7995 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7997 RSurf_SetupDepthAndCulling();
7998 GL_AlphaTest(false);
7999 R_Mesh_ColorPointer(NULL, 0, 0);
8000 R_Mesh_ResetTextureState();
8001 R_SetupGenericShader(false);
8002 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8004 GL_BlendFunc(GL_ONE, GL_ZERO);
8006 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8008 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8009 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8010 else if (!rsurface.texture->currentnumlayers)
8012 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8014 // transparent surfaces get pushed off into the transparent queue
8015 int surfacelistindex;
8016 const msurface_t *surface;
8017 vec3_t tempcenter, center;
8018 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8020 surface = texturesurfacelist[surfacelistindex];
8021 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8022 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8023 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8024 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8025 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8030 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8031 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8036 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8040 // break the surface list down into batches by texture and use of lightmapping
8041 for (i = 0;i < numsurfaces;i = j)
8044 // texture is the base texture pointer, rsurface.texture is the
8045 // current frame/skin the texture is directing us to use (for example
8046 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8047 // use skin 1 instead)
8048 texture = surfacelist[i]->texture;
8049 rsurface.texture = R_GetCurrentTexture(texture);
8050 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8051 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8053 // if this texture is not the kind we want, skip ahead to the next one
8054 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8058 // simply scan ahead until we find a different texture or lightmap state
8059 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8061 // render the range of surfaces
8062 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
8066 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
8071 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8073 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8075 RSurf_SetupDepthAndCulling();
8076 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8077 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8079 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8081 RSurf_SetupDepthAndCulling();
8082 GL_AlphaTest(false);
8083 R_Mesh_ColorPointer(NULL, 0, 0);
8084 R_Mesh_ResetTextureState();
8085 R_SetupGenericShader(false);
8086 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8088 GL_BlendFunc(GL_ONE, GL_ZERO);
8089 GL_Color(0, 0, 0, 1);
8090 GL_DepthTest(writedepth);
8091 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8093 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8095 RSurf_SetupDepthAndCulling();
8096 GL_AlphaTest(false);
8097 R_Mesh_ColorPointer(NULL, 0, 0);
8098 R_Mesh_ResetTextureState();
8099 R_SetupGenericShader(false);
8100 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8102 GL_BlendFunc(GL_ONE, GL_ZERO);
8104 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8106 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8107 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8108 else if (!rsurface.texture->currentnumlayers)
8110 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8112 // transparent surfaces get pushed off into the transparent queue
8113 int surfacelistindex;
8114 const msurface_t *surface;
8115 vec3_t tempcenter, center;
8116 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8118 surface = texturesurfacelist[surfacelistindex];
8119 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8120 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8121 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8122 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8123 if (queueentity->transparent_offset) // transparent offset
8125 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8126 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8127 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8129 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8134 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8135 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8140 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8144 // break the surface list down into batches by texture and use of lightmapping
8145 for (i = 0;i < numsurfaces;i = j)
8148 // texture is the base texture pointer, rsurface.texture is the
8149 // current frame/skin the texture is directing us to use (for example
8150 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8151 // use skin 1 instead)
8152 texture = surfacelist[i]->texture;
8153 rsurface.texture = R_GetCurrentTexture(texture);
8154 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8155 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8157 // if this texture is not the kind we want, skip ahead to the next one
8158 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8162 // simply scan ahead until we find a different texture or lightmap state
8163 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8165 // render the range of surfaces
8166 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8170 float locboxvertex3f[6*4*3] =
8172 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8173 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8174 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8175 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8176 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8177 1,0,0, 0,0,0, 0,1,0, 1,1,0
8180 unsigned short locboxelements[6*2*3] =
8190 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8193 cl_locnode_t *loc = (cl_locnode_t *)ent;
8195 float vertex3f[6*4*3];
8197 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8198 GL_DepthMask(false);
8199 GL_DepthRange(0, 1);
8200 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8202 GL_CullFace(GL_NONE);
8203 R_Mesh_Matrix(&identitymatrix);
8205 R_Mesh_VertexPointer(vertex3f, 0, 0);
8206 R_Mesh_ColorPointer(NULL, 0, 0);
8207 R_Mesh_ResetTextureState();
8208 R_SetupGenericShader(false);
8211 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8212 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8213 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8214 surfacelist[0] < 0 ? 0.5f : 0.125f);
8216 if (VectorCompare(loc->mins, loc->maxs))
8218 VectorSet(size, 2, 2, 2);
8219 VectorMA(loc->mins, -0.5f, size, mins);
8223 VectorCopy(loc->mins, mins);
8224 VectorSubtract(loc->maxs, loc->mins, size);
8227 for (i = 0;i < 6*4*3;)
8228 for (j = 0;j < 3;j++, i++)
8229 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8231 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8234 void R_DrawLocs(void)
8237 cl_locnode_t *loc, *nearestloc;
8239 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8240 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8242 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8243 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8247 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8249 if (decalsystem->decals)
8250 Mem_Free(decalsystem->decals);
8251 memset(decalsystem, 0, sizeof(*decalsystem));
8254 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)
8261 // expand or initialize the system
8262 if (decalsystem->maxdecals <= decalsystem->numdecals)
8264 decalsystem_t old = *decalsystem;
8265 qboolean useshortelements;
8266 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8267 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8268 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)));
8269 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8270 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8271 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8272 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8273 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8274 if (decalsystem->numdecals)
8275 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8277 Mem_Free(old.decals);
8278 for (i = 0;i < decalsystem->maxdecals*3;i++)
8279 decalsystem->element3i[i] = i;
8280 if (useshortelements)
8281 for (i = 0;i < decalsystem->maxdecals*3;i++)
8282 decalsystem->element3s[i] = i;
8285 // grab a decal and search for another free slot for the next one
8286 maxdecals = decalsystem->maxdecals;
8287 decals = decalsystem->decals;
8288 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8289 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8291 decalsystem->freedecal = i;
8292 if (decalsystem->numdecals <= i)
8293 decalsystem->numdecals = i + 1;
8295 // initialize the decal
8297 decal->triangleindex = triangleindex;
8298 decal->surfaceindex = surfaceindex;
8299 decal->decalsequence = decalsequence;
8300 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8301 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8302 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8303 decal->color4ub[0][3] = 255;
8304 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8305 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8306 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8307 decal->color4ub[1][3] = 255;
8308 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8309 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8310 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8311 decal->color4ub[2][3] = 255;
8312 decal->vertex3f[0][0] = v0[0];
8313 decal->vertex3f[0][1] = v0[1];
8314 decal->vertex3f[0][2] = v0[2];
8315 decal->vertex3f[1][0] = v1[0];
8316 decal->vertex3f[1][1] = v1[1];
8317 decal->vertex3f[1][2] = v1[2];
8318 decal->vertex3f[2][0] = v2[0];
8319 decal->vertex3f[2][1] = v2[1];
8320 decal->vertex3f[2][2] = v2[2];
8321 decal->texcoord2f[0][0] = t0[0];
8322 decal->texcoord2f[0][1] = t0[1];
8323 decal->texcoord2f[1][0] = t1[0];
8324 decal->texcoord2f[1][1] = t1[1];
8325 decal->texcoord2f[2][0] = t2[0];
8326 decal->texcoord2f[2][1] = t2[1];
8329 extern cvar_t cl_decals_bias;
8330 extern cvar_t cl_decals_models;
8331 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8332 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)
8334 matrix4x4_t projection;
8335 decalsystem_t *decalsystem;
8338 const float *vertex3f;
8339 const msurface_t *surface;
8340 const msurface_t *surfaces;
8341 const int *surfacelist;
8342 const texture_t *texture;
8346 int surfacelistindex;
8349 int decalsurfaceindex;
8354 float localorigin[3];
8355 float localnormal[3];
8366 float points[2][9][3];
8370 decalsystem = &ent->decalsystem;
8372 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8374 R_DecalSystem_Reset(&ent->decalsystem);
8378 if (!model->brush.data_nodes && !cl_decals_models.integer)
8380 if (decalsystem->model)
8381 R_DecalSystem_Reset(decalsystem);
8385 if (decalsystem->model != model)
8386 R_DecalSystem_Reset(decalsystem);
8387 decalsystem->model = model;
8389 RSurf_ActiveModelEntity(ent, false, false);
8391 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8392 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8393 VectorNormalize(localnormal);
8394 localsize = worldsize*rsurface.inversematrixscale;
8395 ilocalsize = 1.0f / localsize;
8396 localmins[0] = localorigin[0] - localsize;
8397 localmins[1] = localorigin[1] - localsize;
8398 localmins[2] = localorigin[2] - localsize;
8399 localmaxs[0] = localorigin[0] + localsize;
8400 localmaxs[1] = localorigin[1] + localsize;
8401 localmaxs[2] = localorigin[2] + localsize;
8403 //VectorCopy(localnormal, planes[4]);
8404 //VectorVectors(planes[4], planes[2], planes[0]);
8405 AnglesFromVectors(angles, localnormal, NULL, false);
8406 AngleVectors(angles, planes[0], planes[2], planes[4]);
8407 VectorNegate(planes[0], planes[1]);
8408 VectorNegate(planes[2], planes[3]);
8409 VectorNegate(planes[4], planes[5]);
8410 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8411 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8412 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8413 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8414 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8415 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8420 matrix4x4_t forwardprojection;
8421 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8422 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8427 float projectionvector[4][3];
8428 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8429 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8430 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8431 projectionvector[0][0] = planes[0][0] * ilocalsize;
8432 projectionvector[0][1] = planes[1][0] * ilocalsize;
8433 projectionvector[0][2] = planes[2][0] * ilocalsize;
8434 projectionvector[1][0] = planes[0][1] * ilocalsize;
8435 projectionvector[1][1] = planes[1][1] * ilocalsize;
8436 projectionvector[1][2] = planes[2][1] * ilocalsize;
8437 projectionvector[2][0] = planes[0][2] * ilocalsize;
8438 projectionvector[2][1] = planes[1][2] * ilocalsize;
8439 projectionvector[2][2] = planes[2][2] * ilocalsize;
8440 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8441 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8442 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8443 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8447 dynamic = model->surfmesh.isanimated;
8448 vertex3f = rsurface.modelvertex3f;
8449 numsurfacelist = model->nummodelsurfaces;
8450 surfacelist = model->sortedmodelsurfaces;
8451 surfaces = model->data_surfaces;
8452 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8454 surfaceindex = surfacelist[surfacelistindex];
8455 surface = surfaces + surfaceindex;
8456 // skip transparent surfaces
8457 texture = surface->texture;
8458 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8460 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8462 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8464 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8465 numvertices = surface->num_vertices;
8466 numtriangles = surface->num_triangles;
8467 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8469 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8471 index = 3*e[cornerindex];
8472 VectorCopy(vertex3f + index, v[cornerindex]);
8475 //TriangleNormal(v[0], v[1], v[2], normal);
8476 //if (DotProduct(normal, localnormal) < 0.0f)
8478 // clip by each of the box planes formed from the projection matrix
8479 // if anything survives, we emit the decal
8480 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]);
8483 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]);
8486 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]);
8489 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]);
8492 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]);
8495 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]);
8498 // some part of the triangle survived, so we have to accept it...
8501 // dynamic always uses the original triangle
8503 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8505 index = 3*e[cornerindex];
8506 VectorCopy(vertex3f + index, v[cornerindex]);
8509 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8511 // convert vertex positions to texcoords
8512 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8513 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8514 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8515 // calculate distance fade from the projection origin
8516 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8517 f = bound(0.0f, f, 1.0f);
8518 c[cornerindex][0] = r * f;
8519 c[cornerindex][1] = g * f;
8520 c[cornerindex][2] = b * f;
8521 c[cornerindex][3] = 1.0f;
8522 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8525 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);
8527 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8528 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);
8533 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8534 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)
8536 int renderentityindex;
8539 entity_render_t *ent;
8541 if (!cl_decals_newsystem.integer)
8544 worldmins[0] = worldorigin[0] - worldsize;
8545 worldmins[1] = worldorigin[1] - worldsize;
8546 worldmins[2] = worldorigin[2] - worldsize;
8547 worldmaxs[0] = worldorigin[0] + worldsize;
8548 worldmaxs[1] = worldorigin[1] + worldsize;
8549 worldmaxs[2] = worldorigin[2] + worldsize;
8551 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8553 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8555 ent = r_refdef.scene.entities[renderentityindex];
8556 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8559 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8563 typedef struct r_decalsystem_splatqueue_s
8572 r_decalsystem_splatqueue_t;
8574 int r_decalsystem_numqueued = 0;
8575 #define MAX_DECALSYSTEM_QUEUE 1024
8576 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8578 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)
8580 r_decalsystem_splatqueue_t *queue;
8582 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8585 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8586 VectorCopy(worldorigin, queue->worldorigin);
8587 VectorCopy(worldnormal, queue->worldnormal);
8588 Vector4Set(queue->color, r, g, b, a);
8589 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8590 queue->worldsize = worldsize;
8591 queue->decalsequence = cl.decalsequence++;
8594 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8597 r_decalsystem_splatqueue_t *queue;
8599 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8600 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);
8601 r_decalsystem_numqueued = 0;
8604 extern cvar_t cl_decals_max;
8605 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8608 decalsystem_t *decalsystem = &ent->decalsystem;
8615 if (!decalsystem->numdecals)
8618 if (r_showsurfaces.integer)
8621 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8623 R_DecalSystem_Reset(decalsystem);
8627 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
8628 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
8630 if (decalsystem->lastupdatetime)
8631 frametime = (cl.time - decalsystem->lastupdatetime);
8634 decalsystem->lastupdatetime = cl.time;
8635 decal = decalsystem->decals;
8636 numdecals = decalsystem->numdecals;
8638 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8640 if (decal->color4ub[0][3])
8642 decal->lived += frametime;
8643 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
8645 memset(decal, 0, sizeof(*decal));
8646 if (decalsystem->freedecal > i)
8647 decalsystem->freedecal = i;
8651 decal = decalsystem->decals;
8652 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
8655 // collapse the array by shuffling the tail decals into the gaps
8658 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
8659 decalsystem->freedecal++;
8660 if (decalsystem->freedecal == numdecals)
8662 decal[decalsystem->freedecal] = decal[--numdecals];
8665 decalsystem->numdecals = numdecals;
8669 // if there are no decals left, reset decalsystem
8670 R_DecalSystem_Reset(decalsystem);
8674 extern skinframe_t *decalskinframe;
8675 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8678 decalsystem_t *decalsystem = &ent->decalsystem;
8688 const unsigned char *surfacevisible = r_refdef.viewcache.world_surfacevisible;
8691 numdecals = decalsystem->numdecals;
8695 if (r_showsurfaces.integer)
8698 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8700 R_DecalSystem_Reset(decalsystem);
8704 // if the model is static it doesn't matter what value we give for
8705 // wantnormals and wanttangents, so this logic uses only rules applicable
8706 // to a model, knowing that they are meaningless otherwise
8707 if (ent == r_refdef.scene.worldentity)
8708 RSurf_ActiveWorldEntity();
8710 RSurf_ActiveModelEntity(ent, false, false);
8712 decalsystem->lastupdatetime = cl.time;
8713 decal = decalsystem->decals;
8715 fadedelay = cl_decals_time.value;
8716 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
8718 // update vertex positions for animated models
8719 v3f = decalsystem->vertex3f;
8720 c4f = decalsystem->color4f;
8721 t2f = decalsystem->texcoord2f;
8722 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8724 if (!decal->color4ub[0][3])
8727 if (decal->surfaceindex >= 0 && !surfacevisible[decal->surfaceindex])
8730 // update color values for fading decals
8731 if (decal->lived >= cl_decals_time.value)
8733 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
8734 alpha *= (1.0f/255.0f);
8737 alpha = 1.0f/255.0f;
8739 c4f[ 0] = decal->color4ub[0][0] * alpha;
8740 c4f[ 1] = decal->color4ub[0][1] * alpha;
8741 c4f[ 2] = decal->color4ub[0][2] * alpha;
8743 c4f[ 4] = decal->color4ub[1][0] * alpha;
8744 c4f[ 5] = decal->color4ub[1][1] * alpha;
8745 c4f[ 6] = decal->color4ub[1][2] * alpha;
8747 c4f[ 8] = decal->color4ub[2][0] * alpha;
8748 c4f[ 9] = decal->color4ub[2][1] * alpha;
8749 c4f[10] = decal->color4ub[2][2] * alpha;
8752 t2f[0] = decal->texcoord2f[0][0];
8753 t2f[1] = decal->texcoord2f[0][1];
8754 t2f[2] = decal->texcoord2f[1][0];
8755 t2f[3] = decal->texcoord2f[1][1];
8756 t2f[4] = decal->texcoord2f[2][0];
8757 t2f[5] = decal->texcoord2f[2][1];
8759 // update vertex positions for animated models
8760 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8762 e = rsurface.modelelement3i + 3*decal->triangleindex;
8763 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8764 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8765 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8769 VectorCopy(decal->vertex3f[0], v3f);
8770 VectorCopy(decal->vertex3f[1], v3f + 3);
8771 VectorCopy(decal->vertex3f[2], v3f + 6);
8782 r_refdef.stats.drawndecals += numtris;
8783 // now render the decals all at once
8784 // (this assumes they all use one particle font texture!)
8785 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);
8786 R_Mesh_ResetTextureState();
8787 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8788 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8789 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8790 R_SetupGenericShader(true);
8791 GL_DepthMask(false);
8792 GL_DepthRange(0, 1);
8793 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
8795 GL_CullFace(GL_NONE);
8796 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8797 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8798 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8799 GL_LockArrays(0, numtris * 3);
8800 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
8801 GL_LockArrays(0, 0);
8805 static void R_DrawModelDecals(void)
8809 // fade faster when there are too many decals
8810 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
8811 for (i = 0;i < r_refdef.scene.numentities;i++)
8812 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
8814 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
8815 for (i = 0;i < r_refdef.scene.numentities;i++)
8816 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
8817 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
8819 R_DecalSystem_ApplySplatEntitiesQueue();
8821 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
8822 for (i = 0;i < r_refdef.scene.numentities;i++)
8823 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
8825 r_refdef.stats.totaldecals += numdecals;
8827 if (r_showsurfaces.integer)
8830 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
8832 if (!r_drawentities.integer)
8835 for (i = 0;i < r_refdef.scene.numentities;i++)
8837 if (!r_refdef.viewcache.entityvisible[i])
8839 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
8840 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
8844 void R_DrawDebugModel(void)
8846 entity_render_t *ent = rsurface.entity;
8847 int i, j, k, l, flagsmask;
8848 const int *elements;
8850 const msurface_t *surface;
8851 dp_model_t *model = ent->model;
8854 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8856 R_Mesh_ColorPointer(NULL, 0, 0);
8857 R_Mesh_ResetTextureState();
8858 R_SetupGenericShader(false);
8859 GL_DepthRange(0, 1);
8860 GL_DepthTest(!r_showdisabledepthtest.integer);
8861 GL_DepthMask(false);
8862 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8864 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8866 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8867 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8869 if (brush->colbrushf && brush->colbrushf->numtriangles)
8871 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8872 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);
8873 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8876 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8878 if (surface->num_collisiontriangles)
8880 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8881 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);
8882 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8887 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8889 if (r_showtris.integer || r_shownormals.integer)
8891 if (r_showdisabledepthtest.integer)
8893 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8894 GL_DepthMask(false);
8898 GL_BlendFunc(GL_ONE, GL_ZERO);
8901 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8903 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8905 rsurface.texture = R_GetCurrentTexture(surface->texture);
8906 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8908 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8909 if (r_showtris.value > 0)
8911 if (!rsurface.texture->currentlayers->depthmask)
8912 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8913 else if (ent == r_refdef.scene.worldentity)
8914 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8916 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8917 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8918 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8919 R_Mesh_ColorPointer(NULL, 0, 0);
8920 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8921 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8922 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8923 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);
8924 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8927 if (r_shownormals.value < 0)
8930 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8932 VectorCopy(rsurface.vertex3f + l * 3, v);
8933 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8934 qglVertex3f(v[0], v[1], v[2]);
8935 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8936 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8937 qglVertex3f(v[0], v[1], v[2]);
8942 if (r_shownormals.value > 0)
8945 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8947 VectorCopy(rsurface.vertex3f + l * 3, v);
8948 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8949 qglVertex3f(v[0], v[1], v[2]);
8950 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8951 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8952 qglVertex3f(v[0], v[1], v[2]);
8957 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8959 VectorCopy(rsurface.vertex3f + l * 3, v);
8960 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8961 qglVertex3f(v[0], v[1], v[2]);
8962 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8963 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8964 qglVertex3f(v[0], v[1], v[2]);
8969 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8971 VectorCopy(rsurface.vertex3f + l * 3, v);
8972 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8973 qglVertex3f(v[0], v[1], v[2]);
8974 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8975 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8976 qglVertex3f(v[0], v[1], v[2]);
8983 rsurface.texture = NULL;
8987 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8988 int r_maxsurfacelist = 0;
8989 const msurface_t **r_surfacelist = NULL;
8990 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8992 int i, j, endj, f, flagsmask;
8994 dp_model_t *model = r_refdef.scene.worldmodel;
8995 msurface_t *surfaces;
8996 unsigned char *update;
8997 int numsurfacelist = 0;
9001 if (r_maxsurfacelist < model->num_surfaces)
9003 r_maxsurfacelist = model->num_surfaces;
9005 Mem_Free((msurface_t**)r_surfacelist);
9006 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9009 RSurf_ActiveWorldEntity();
9011 surfaces = model->data_surfaces;
9012 update = model->brushq1.lightmapupdateflags;
9014 // update light styles on this submodel
9015 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9017 model_brush_lightstyleinfo_t *style;
9018 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9020 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9022 int *list = style->surfacelist;
9023 style->value = r_refdef.scene.lightstylevalue[style->style];
9024 for (j = 0;j < style->numsurfaces;j++)
9025 update[list[j]] = true;
9030 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9035 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9041 rsurface.uselightmaptexture = false;
9042 rsurface.texture = NULL;
9043 rsurface.rtlight = NULL;
9045 // add visible surfaces to draw list
9046 for (i = 0;i < model->nummodelsurfaces;i++)
9048 j = model->sortedmodelsurfaces[i];
9049 if (r_refdef.viewcache.world_surfacevisible[j])
9050 r_surfacelist[numsurfacelist++] = surfaces + j;
9052 // update lightmaps if needed
9054 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9055 if (r_refdef.viewcache.world_surfacevisible[j])
9057 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9058 // don't do anything if there were no surfaces
9059 if (!numsurfacelist)
9061 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9064 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
9065 GL_AlphaTest(false);
9067 // add to stats if desired
9068 if (r_speeds.integer && !skysurfaces && !depthonly)
9070 r_refdef.stats.world_surfaces += numsurfacelist;
9071 for (j = 0;j < numsurfacelist;j++)
9072 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9075 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9078 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
9080 int i, j, endj, f, flagsmask;
9082 dp_model_t *model = ent->model;
9083 msurface_t *surfaces;
9084 unsigned char *update;
9085 int numsurfacelist = 0;
9089 if (r_maxsurfacelist < model->num_surfaces)
9091 r_maxsurfacelist = model->num_surfaces;
9093 Mem_Free((msurface_t **)r_surfacelist);
9094 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9097 // if the model is static it doesn't matter what value we give for
9098 // wantnormals and wanttangents, so this logic uses only rules applicable
9099 // to a model, knowing that they are meaningless otherwise
9100 if (ent == r_refdef.scene.worldentity)
9101 RSurf_ActiveWorldEntity();
9102 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9103 RSurf_ActiveModelEntity(ent, false, false);
9105 RSurf_ActiveModelEntity(ent, false, false);
9107 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && vid.support.arb_fragment_shader);
9109 surfaces = model->data_surfaces;
9110 update = model->brushq1.lightmapupdateflags;
9112 // update light styles
9113 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9115 model_brush_lightstyleinfo_t *style;
9116 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9118 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9120 int *list = style->surfacelist;
9121 style->value = r_refdef.scene.lightstylevalue[style->style];
9122 for (j = 0;j < style->numsurfaces;j++)
9123 update[list[j]] = true;
9128 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9133 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9139 rsurface.uselightmaptexture = false;
9140 rsurface.texture = NULL;
9141 rsurface.rtlight = NULL;
9143 // add visible surfaces to draw list
9144 for (i = 0;i < model->nummodelsurfaces;i++)
9145 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9146 // don't do anything if there were no surfaces
9147 if (!numsurfacelist)
9149 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9152 // update lightmaps if needed
9154 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9156 R_BuildLightMap(ent, surfaces + j);
9157 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
9158 GL_AlphaTest(false);
9160 // add to stats if desired
9161 if (r_speeds.integer && !skysurfaces && !depthonly)
9163 r_refdef.stats.entities_surfaces += numsurfacelist;
9164 for (j = 0;j < numsurfacelist;j++)
9165 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9168 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9171 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
9173 static texture_t texture;
9174 static msurface_t surface;
9175 const msurface_t *surfacelist = &surface;
9177 // fake enough texture and surface state to render this geometry
9179 texture.update_lastrenderframe = -1; // regenerate this texture
9180 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9181 texture.currentskinframe = skinframe;
9182 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9183 texture.specularscalemod = 1;
9184 texture.specularpowermod = 1;
9186 surface.texture = &texture;
9187 surface.num_triangles = numtriangles;
9188 surface.num_firsttriangle = firsttriangle;
9189 surface.num_vertices = numvertices;
9190 surface.num_firstvertex = firstvertex;
9193 rsurface.texture = R_GetCurrentTexture(surface.texture);
9194 rsurface.uselightmaptexture = false;
9195 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);