2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
38 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
47 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
48 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
49 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
50 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
51 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
53 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
55 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
56 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
57 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
58 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
59 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
60 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
61 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
62 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
63 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
64 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
65 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
66 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
67 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
68 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
69 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
70 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
71 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
72 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
73 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
74 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
75 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
76 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
77 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
78 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
79 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
80 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
81 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
82 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
83 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
84 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
85 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
86 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
87 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
88 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
89 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
90 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
91 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
92 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
93 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
94 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
95 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
97 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
98 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
99 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
100 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
101 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
102 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
103 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
104 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
106 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
108 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
109 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
110 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
111 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
112 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
113 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
114 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
115 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
116 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
117 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
118 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
120 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
121 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
122 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
123 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
124 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
126 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
127 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
128 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
129 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
131 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
132 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
133 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
134 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
135 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
136 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
137 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
139 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
140 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
141 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
142 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
144 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
146 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
148 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
150 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
151 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
152 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
153 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
154 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
155 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
156 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
158 extern cvar_t v_glslgamma;
160 extern qboolean v_flipped_state;
162 static struct r_bloomstate_s
167 int bloomwidth, bloomheight;
169 int screentexturewidth, screentextureheight;
170 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
172 int bloomtexturewidth, bloomtextureheight;
173 rtexture_t *texture_bloom;
175 // arrays for rendering the screen passes
176 float screentexcoord2f[8];
177 float bloomtexcoord2f[8];
178 float offsettexcoord2f[8];
180 r_viewport_t viewport;
184 r_waterstate_t r_waterstate;
186 /// shadow volume bsp struct with automatically growing nodes buffer
189 rtexture_t *r_texture_blanknormalmap;
190 rtexture_t *r_texture_white;
191 rtexture_t *r_texture_grey128;
192 rtexture_t *r_texture_black;
193 rtexture_t *r_texture_notexture;
194 rtexture_t *r_texture_whitecube;
195 rtexture_t *r_texture_normalizationcube;
196 rtexture_t *r_texture_fogattenuation;
197 rtexture_t *r_texture_gammaramps;
198 unsigned int r_texture_gammaramps_serial;
199 //rtexture_t *r_texture_fogintensity;
201 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
202 unsigned int r_numqueries;
203 unsigned int r_maxqueries;
205 typedef struct r_qwskincache_s
207 char name[MAX_QPATH];
208 skinframe_t *skinframe;
212 static r_qwskincache_t *r_qwskincache;
213 static int r_qwskincache_size;
215 /// vertex coordinates for a quad that covers the screen exactly
216 const float r_screenvertex3f[12] =
224 extern void R_DrawModelShadows(void);
226 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
229 for (i = 0;i < verts;i++)
240 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
243 for (i = 0;i < verts;i++)
253 // FIXME: move this to client?
256 if (gamemode == GAME_NEHAHRA)
258 Cvar_Set("gl_fogenable", "0");
259 Cvar_Set("gl_fogdensity", "0.2");
260 Cvar_Set("gl_fogred", "0.3");
261 Cvar_Set("gl_foggreen", "0.3");
262 Cvar_Set("gl_fogblue", "0.3");
264 r_refdef.fog_density = 0;
265 r_refdef.fog_red = 0;
266 r_refdef.fog_green = 0;
267 r_refdef.fog_blue = 0;
268 r_refdef.fog_alpha = 1;
269 r_refdef.fog_start = 0;
270 r_refdef.fog_end = 16384;
271 r_refdef.fog_height = 1<<30;
272 r_refdef.fog_fadedepth = 128;
275 static void R_BuildBlankTextures(void)
277 unsigned char data[4];
278 data[2] = 128; // normal X
279 data[1] = 128; // normal Y
280 data[0] = 255; // normal Z
281 data[3] = 128; // height
282 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
287 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
292 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
297 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
300 static void R_BuildNoTexture(void)
303 unsigned char pix[16][16][4];
304 // this makes a light grey/dark grey checkerboard texture
305 for (y = 0;y < 16;y++)
307 for (x = 0;x < 16;x++)
309 if ((y < 8) ^ (x < 8))
325 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
328 static void R_BuildWhiteCube(void)
330 unsigned char data[6*1*1*4];
331 memset(data, 255, sizeof(data));
332 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
335 static void R_BuildNormalizationCube(void)
339 vec_t s, t, intensity;
341 unsigned char data[6][NORMSIZE][NORMSIZE][4];
342 for (side = 0;side < 6;side++)
344 for (y = 0;y < NORMSIZE;y++)
346 for (x = 0;x < NORMSIZE;x++)
348 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
349 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
384 intensity = 127.0f / sqrt(DotProduct(v, v));
385 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
386 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
387 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
388 data[side][y][x][3] = 255;
392 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
395 static void R_BuildFogTexture(void)
399 unsigned char data1[FOGWIDTH][4];
400 //unsigned char data2[FOGWIDTH][4];
403 r_refdef.fogmasktable_start = r_refdef.fog_start;
404 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
405 r_refdef.fogmasktable_range = r_refdef.fogrange;
406 r_refdef.fogmasktable_density = r_refdef.fog_density;
408 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
409 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
411 d = (x * r - r_refdef.fogmasktable_start);
412 if(developer.integer >= 100)
413 Con_Printf("%f ", d);
415 if (r_fog_exp2.integer)
416 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
418 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
419 if(developer.integer >= 100)
420 Con_Printf(" : %f ", alpha);
421 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
422 if(developer.integer >= 100)
423 Con_Printf(" = %f\n", alpha);
424 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
427 for (x = 0;x < FOGWIDTH;x++)
429 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
434 //data2[x][0] = 255 - b;
435 //data2[x][1] = 255 - b;
436 //data2[x][2] = 255 - b;
439 if (r_texture_fogattenuation)
441 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
442 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
446 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
447 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
451 static const char *builtinshaderstring =
452 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
453 "// written by Forest 'LordHavoc' Hale\n"
455 "// enable various extensions depending on permutation:\n"
457 "#ifdef USESHADOWMAPRECT\n"
458 "# extension GL_ARB_texture_rectangle : enable\n"
461 "#ifdef USESHADOWMAP2D\n"
462 "# ifdef GL_EXT_gpu_shader4\n"
463 "# extension GL_EXT_gpu_shader4 : enable\n"
465 "# ifdef GL_ARB_texture_gather\n"
466 "# extension GL_ARB_texture_gather : enable\n"
468 "# ifdef GL_AMD_texture_texture4\n"
469 "# extension GL_AMD_texture_texture4 : enable\n"
474 "#ifdef USESHADOWMAPCUBE\n"
475 "# extension GL_EXT_gpu_shader4 : enable\n"
478 "#ifdef USESHADOWSAMPLER\n"
479 "# extension GL_ARB_shadow : enable\n"
482 "// common definitions between vertex shader and fragment shader:\n"
484 "//#ifdef __GLSL_CG_DATA_TYPES\n"
485 "//# define myhalf half\n"
486 "//# define myhalf2 half2\n"
487 "//# define myhalf3half3\n"
488 "//# define myhalf4 half4\n"
490 "# define myhalf float\n"
491 "# define myhalf2 vec2\n"
492 "# define myhalf3 vec3\n"
493 "# define myhalf4 vec4\n"
496 "#ifdef USEFOGINSIDE\n"
499 "# ifdef USEFOGOUTSIDE\n"
504 "#ifdef MODE_DEPTH_OR_SHADOW\n"
506 "# ifdef VERTEX_SHADER\n"
509 " gl_Position = ftransform();\n"
514 "#ifdef MODE_SHOWDEPTH\n"
515 "# ifdef VERTEX_SHADER\n"
518 " gl_Position = ftransform();\n"
519 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
522 "# ifdef FRAGMENT_SHADER\n"
525 " gl_FragColor = gl_Color;\n"
529 "#else // !MODE_SHOWDEPTH\n"
531 "#ifdef MODE_POSTPROCESS\n"
532 "# ifdef VERTEX_SHADER\n"
535 " gl_FrontColor = gl_Color;\n"
536 " gl_Position = ftransform();\n"
537 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
539 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
543 "# ifdef FRAGMENT_SHADER\n"
545 "uniform sampler2D Texture_First;\n"
547 "uniform sampler2D Texture_Second;\n"
549 "#ifdef USEGAMMARAMPS\n"
550 "uniform sampler2D Texture_GammaRamps;\n"
552 "#ifdef USESATURATION\n"
553 "uniform float Saturation;\n"
555 "#ifdef USEVIEWTINT\n"
556 "uniform vec4 TintColor;\n"
558 "//uncomment these if you want to use them:\n"
559 "uniform vec4 UserVec1;\n"
560 "// uniform vec4 UserVec2;\n"
561 "// uniform vec4 UserVec3;\n"
562 "// uniform vec4 UserVec4;\n"
563 "// uniform float ClientTime;\n"
564 "uniform vec2 PixelSize;\n"
567 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
569 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
571 "#ifdef USEVIEWTINT\n"
572 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
575 "#ifdef USEPOSTPROCESSING\n"
576 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
577 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
578 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
579 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
580 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
581 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
582 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
583 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
586 "#ifdef USESATURATION\n"
587 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
588 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
589 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
590 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
593 "#ifdef USEGAMMARAMPS\n"
594 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
595 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
596 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
603 "#ifdef MODE_GENERIC\n"
604 "# ifdef VERTEX_SHADER\n"
607 " gl_FrontColor = gl_Color;\n"
608 "# ifdef USEDIFFUSE\n"
609 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
611 "# ifdef USESPECULAR\n"
612 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
614 " gl_Position = ftransform();\n"
617 "# ifdef FRAGMENT_SHADER\n"
619 "# ifdef USEDIFFUSE\n"
620 "uniform sampler2D Texture_First;\n"
622 "# ifdef USESPECULAR\n"
623 "uniform sampler2D Texture_Second;\n"
628 " gl_FragColor = gl_Color;\n"
629 "# ifdef USEDIFFUSE\n"
630 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
633 "# ifdef USESPECULAR\n"
634 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
636 "# ifdef USECOLORMAPPING\n"
637 " gl_FragColor *= tex2;\n"
640 " gl_FragColor += tex2;\n"
642 "# ifdef USEVERTEXTEXTUREBLEND\n"
643 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
648 "#else // !MODE_GENERIC\n"
649 "#ifdef MODE_BLOOMBLUR\n"
650 "# ifdef VERTEX_SHADER\n"
653 " gl_FrontColor = gl_Color;\n"
654 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
655 " gl_Position = ftransform();\n"
658 "# ifdef FRAGMENT_SHADER\n"
660 "uniform sampler2D Texture_First;\n"
661 "uniform vec4 BloomBlur_Parameters;\n"
666 " vec2 tc = gl_TexCoord[0].xy;\n"
667 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
668 " tc += BloomBlur_Parameters.xy;\n"
669 " for (i = 1;i < SAMPLES;i++)\n"
671 " color += texture2D(Texture_First, tc).rgb;\n"
672 " tc += BloomBlur_Parameters.xy;\n"
674 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
678 "#else // !MODE_BLOOMBLUR\n"
680 "varying vec2 TexCoord;\n"
681 "#ifdef USEVERTEXTEXTUREBLEND\n"
682 "varying vec2 TexCoord2;\n"
684 "varying vec2 TexCoordLightmap;\n"
686 "#ifdef MODE_LIGHTSOURCE\n"
687 "varying vec3 CubeVector;\n"
690 "#ifdef MODE_LIGHTSOURCE\n"
691 "varying vec3 LightVector;\n"
693 "#ifdef MODE_LIGHTDIRECTION\n"
694 "varying vec3 LightVector;\n"
697 "varying vec3 EyeVector;\n"
699 "varying vec3 EyeVectorModelSpace;\n"
700 "varying float FogPlaneVertexDist;\n"
703 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
704 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
705 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
707 "#ifdef MODE_WATER\n"
708 "varying vec4 ModelViewProjectionPosition;\n"
710 "#ifdef MODE_REFRACTION\n"
711 "varying vec4 ModelViewProjectionPosition;\n"
713 "#ifdef USEREFLECTION\n"
714 "varying vec4 ModelViewProjectionPosition;\n"
721 "// vertex shader specific:\n"
722 "#ifdef VERTEX_SHADER\n"
724 "uniform vec3 LightPosition;\n"
725 "uniform vec3 EyePosition;\n"
726 "uniform vec3 LightDir;\n"
727 "uniform vec4 FogPlane;\n"
729 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
733 " gl_FrontColor = gl_Color;\n"
734 " // copy the surface texcoord\n"
735 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
736 "#ifdef USEVERTEXTEXTUREBLEND\n"
737 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
739 "#ifndef MODE_LIGHTSOURCE\n"
740 "# ifndef MODE_LIGHTDIRECTION\n"
741 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
745 "#ifdef MODE_LIGHTSOURCE\n"
746 " // transform vertex position into light attenuation/cubemap space\n"
747 " // (-1 to +1 across the light box)\n"
748 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
750 " // transform unnormalized light direction into tangent space\n"
751 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
752 " // normalize it per pixel)\n"
753 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
754 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
755 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
756 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
759 "#ifdef MODE_LIGHTDIRECTION\n"
760 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
761 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
762 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
765 " // transform unnormalized eye direction into tangent space\n"
767 " vec3 EyeVectorModelSpace;\n"
769 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
770 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
771 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
772 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
775 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
778 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
779 " VectorS = gl_MultiTexCoord1.xyz;\n"
780 " VectorT = gl_MultiTexCoord2.xyz;\n"
781 " VectorR = gl_MultiTexCoord3.xyz;\n"
784 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
785 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
786 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
787 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
790 "// transform vertex to camera space, using ftransform to match non-VS\n"
792 " gl_Position = ftransform();\n"
794 "#ifdef MODE_WATER\n"
795 " ModelViewProjectionPosition = gl_Position;\n"
797 "#ifdef MODE_REFRACTION\n"
798 " ModelViewProjectionPosition = gl_Position;\n"
800 "#ifdef USEREFLECTION\n"
801 " ModelViewProjectionPosition = gl_Position;\n"
805 "#endif // VERTEX_SHADER\n"
810 "// fragment shader specific:\n"
811 "#ifdef FRAGMENT_SHADER\n"
813 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
814 "uniform sampler2D Texture_Normal;\n"
815 "uniform sampler2D Texture_Color;\n"
816 "uniform sampler2D Texture_Gloss;\n"
817 "uniform sampler2D Texture_Glow;\n"
818 "uniform sampler2D Texture_SecondaryNormal;\n"
819 "uniform sampler2D Texture_SecondaryColor;\n"
820 "uniform sampler2D Texture_SecondaryGloss;\n"
821 "uniform sampler2D Texture_SecondaryGlow;\n"
822 "uniform sampler2D Texture_Pants;\n"
823 "uniform sampler2D Texture_Shirt;\n"
824 "uniform sampler2D Texture_FogMask;\n"
825 "uniform sampler2D Texture_Lightmap;\n"
826 "uniform sampler2D Texture_Deluxemap;\n"
827 "uniform sampler2D Texture_Refraction;\n"
828 "uniform sampler2D Texture_Reflection;\n"
829 "uniform sampler2D Texture_Attenuation;\n"
830 "uniform samplerCube Texture_Cube;\n"
832 "#define showshadowmap 0\n"
834 "#ifdef USESHADOWMAPRECT\n"
835 "# ifdef USESHADOWSAMPLER\n"
836 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
838 "uniform sampler2DRect Texture_ShadowMapRect;\n"
842 "#ifdef USESHADOWMAP2D\n"
843 "# ifdef USESHADOWSAMPLER\n"
844 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
846 "uniform sampler2D Texture_ShadowMap2D;\n"
850 "#ifdef USESHADOWMAPVSDCT\n"
851 "uniform samplerCube Texture_CubeProjection;\n"
854 "#ifdef USESHADOWMAPCUBE\n"
855 "# ifdef USESHADOWSAMPLER\n"
856 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
858 "uniform samplerCube Texture_ShadowMapCube;\n"
862 "uniform myhalf3 LightColor;\n"
863 "uniform myhalf3 AmbientColor;\n"
864 "uniform myhalf3 DiffuseColor;\n"
865 "uniform myhalf3 SpecularColor;\n"
866 "uniform myhalf3 Color_Pants;\n"
867 "uniform myhalf3 Color_Shirt;\n"
868 "uniform myhalf3 FogColor;\n"
870 "uniform myhalf4 TintColor;\n"
873 "//#ifdef MODE_WATER\n"
874 "uniform vec4 DistortScaleRefractReflect;\n"
875 "uniform vec4 ScreenScaleRefractReflect;\n"
876 "uniform vec4 ScreenCenterRefractReflect;\n"
877 "uniform myhalf4 RefractColor;\n"
878 "uniform myhalf4 ReflectColor;\n"
879 "uniform myhalf ReflectFactor;\n"
880 "uniform myhalf ReflectOffset;\n"
882 "//# ifdef MODE_REFRACTION\n"
883 "//uniform vec4 DistortScaleRefractReflect;\n"
884 "//uniform vec4 ScreenScaleRefractReflect;\n"
885 "//uniform vec4 ScreenCenterRefractReflect;\n"
886 "//uniform myhalf4 RefractColor;\n"
887 "//# ifdef USEREFLECTION\n"
888 "//uniform myhalf4 ReflectColor;\n"
891 "//# ifdef USEREFLECTION\n"
892 "//uniform vec4 DistortScaleRefractReflect;\n"
893 "//uniform vec4 ScreenScaleRefractReflect;\n"
894 "//uniform vec4 ScreenCenterRefractReflect;\n"
895 "//uniform myhalf4 ReflectColor;\n"
900 "uniform myhalf3 GlowColor;\n"
901 "uniform myhalf SceneBrightness;\n"
903 "uniform float OffsetMapping_Scale;\n"
904 "uniform float OffsetMapping_Bias;\n"
905 "uniform float FogRangeRecip;\n"
906 "uniform float FogPlaneViewDist;\n"
907 "uniform float FogHeightFade;\n"
909 "uniform myhalf AmbientScale;\n"
910 "uniform myhalf DiffuseScale;\n"
911 "uniform myhalf SpecularScale;\n"
912 "uniform myhalf SpecularPower;\n"
914 "#ifdef USEOFFSETMAPPING\n"
915 "vec2 OffsetMapping(vec2 TexCoord)\n"
917 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
918 " // 14 sample relief mapping: linear search and then binary search\n"
919 " // this basically steps forward a small amount repeatedly until it finds\n"
920 " // itself inside solid, then jitters forward and back using decreasing\n"
921 " // amounts to find the impact\n"
922 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
923 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
924 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
925 " vec3 RT = vec3(TexCoord, 1);\n"
926 " OffsetVector *= 0.1;\n"
927 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
928 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
929 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
930 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
931 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
932 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
933 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
934 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
935 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
936 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
937 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
938 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
939 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
940 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
943 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
944 " // this basically moves forward the full distance, and then backs up based\n"
945 " // on height of samples\n"
946 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
947 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
948 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
949 " TexCoord += OffsetVector;\n"
950 " OffsetVector *= 0.333;\n"
951 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
952 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
953 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
954 " return TexCoord;\n"
957 "#endif // USEOFFSETMAPPING\n"
959 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
960 "uniform vec2 ShadowMap_TextureScale;\n"
961 "uniform vec4 ShadowMap_Parameters;\n"
964 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
965 "vec3 GetShadowMapTC2D(vec3 dir)\n"
967 " vec3 adir = abs(dir);\n"
968 "# ifndef USESHADOWMAPVSDCT\n"
972 " if (adir.x > adir.y)\n"
974 " if (adir.x > adir.z) // X\n"
978 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
984 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
989 " if (adir.y > adir.z) // Y\n"
993 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
999 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1003 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1004 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1005 " stc.z += ShadowMap_Parameters.z;\n"
1006 "# if showshadowmap\n"
1007 " stc.xy *= ShadowMap_TextureScale;\n"
1011 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1012 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1013 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1014 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1015 " stc.z += ShadowMap_Parameters.z;\n"
1016 "# if showshadowmap\n"
1017 " stc.xy *= ShadowMap_TextureScale;\n"
1022 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1024 "#ifdef USESHADOWMAPCUBE\n"
1025 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1027 " vec3 adir = abs(dir);\n"
1028 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1032 "#if !showshadowmap\n"
1033 "# ifdef USESHADOWMAPRECT\n"
1034 "float ShadowMapCompare(vec3 dir)\n"
1036 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1038 "# ifdef USESHADOWSAMPLER\n"
1040 "# ifdef USESHADOWMAPPCF\n"
1041 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1042 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1044 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1049 "# ifdef USESHADOWMAPPCF\n"
1050 "# if USESHADOWMAPPCF > 1\n"
1051 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1052 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1053 " vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1054 " vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
1055 " vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
1056 " vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
1057 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1058 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1060 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1061 " vec2 offset = fract(shadowmaptc.xy);\n"
1062 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1063 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1064 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1065 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1066 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1069 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1077 "# ifdef USESHADOWMAP2D\n"
1078 "float ShadowMapCompare(vec3 dir)\n"
1080 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1083 "# ifdef USESHADOWSAMPLER\n"
1084 "# ifdef USESHADOWMAPPCF\n"
1085 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1086 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1087 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1089 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1092 "# ifdef USESHADOWMAPPCF\n"
1093 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1094 "# ifdef GL_ARB_texture_gather\n"
1095 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1097 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1099 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1100 " center *= ShadowMap_TextureScale;\n"
1101 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1102 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1103 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1104 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1105 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1106 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1107 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1109 "# ifdef GL_EXT_gpu_shader4\n"
1110 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1112 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1114 "# if USESHADOWMAPPCF > 1\n"
1115 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1116 " center *= ShadowMap_TextureScale;\n"
1117 " vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1118 " vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
1119 " vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
1120 " vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
1121 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1122 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1124 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1125 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1126 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1127 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1128 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1129 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1133 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1140 "# ifdef USESHADOWMAPCUBE\n"
1141 "float ShadowMapCompare(vec3 dir)\n"
1143 " // apply depth texture cubemap as light filter\n"
1144 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1146 "# ifdef USESHADOWSAMPLER\n"
1147 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1149 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1156 "#ifdef MODE_WATER\n"
1161 "#ifdef USEOFFSETMAPPING\n"
1162 " // apply offsetmapping\n"
1163 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1164 "#define TexCoord TexCoordOffset\n"
1167 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1168 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1169 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1170 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1171 " // FIXME temporary hack to detect the case that the reflection\n"
1172 " // gets blackened at edges due to leaving the area that contains actual\n"
1174 " // Remove this 'ack once we have a better way to stop this thing from\n"
1176 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1177 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1178 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1179 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1180 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1181 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1182 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1183 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1184 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1185 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1186 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1187 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1190 "#else // !MODE_WATER\n"
1191 "#ifdef MODE_REFRACTION\n"
1193 "// refraction pass\n"
1196 "#ifdef USEOFFSETMAPPING\n"
1197 " // apply offsetmapping\n"
1198 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1199 "#define TexCoord TexCoordOffset\n"
1202 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1203 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1204 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1205 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1206 " // FIXME temporary hack to detect the case that the reflection\n"
1207 " // gets blackened at edges due to leaving the area that contains actual\n"
1209 " // Remove this 'ack once we have a better way to stop this thing from\n"
1211 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1212 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1213 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1214 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1215 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1216 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1219 "#else // !MODE_REFRACTION\n"
1222 "#ifdef USEOFFSETMAPPING\n"
1223 " // apply offsetmapping\n"
1224 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1225 "#define TexCoord TexCoordOffset\n"
1228 " // combine the diffuse textures (base, pants, shirt)\n"
1229 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1230 "#ifdef USECOLORMAPPING\n"
1231 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1233 "#ifdef USEVERTEXTEXTUREBLEND\n"
1234 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1235 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1236 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1237 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1239 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1242 "#ifdef USEDIFFUSE\n"
1243 " // get the surface normal and the gloss color\n"
1244 "# ifdef USEVERTEXTEXTUREBLEND\n"
1245 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1246 "# ifdef USESPECULAR\n"
1247 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1250 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1251 "# ifdef USESPECULAR\n"
1252 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1259 "#ifdef MODE_LIGHTSOURCE\n"
1260 " // light source\n"
1262 " // calculate surface normal, light normal, and specular normal\n"
1263 " // compute color intensity for the two textures (colormap and glossmap)\n"
1264 " // scale by light color and attenuation as efficiently as possible\n"
1265 " // (do as much scalar math as possible rather than vector math)\n"
1266 "# ifdef USEDIFFUSE\n"
1267 " // get the light normal\n"
1268 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1270 "# ifdef USESPECULAR\n"
1271 "# ifndef USEEXACTSPECULARMATH\n"
1272 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1275 " // calculate directional shading\n"
1276 "# ifdef USEEXACTSPECULARMATH\n"
1277 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
1279 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * glosscolor);\n"
1282 "# ifdef USEDIFFUSE\n"
1283 " // calculate directional shading\n"
1284 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1286 " // calculate directionless shading\n"
1287 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1291 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1292 "#if !showshadowmap\n"
1293 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1297 "# ifdef USECUBEFILTER\n"
1298 " // apply light cubemap filter\n"
1299 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1300 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1302 "#endif // MODE_LIGHTSOURCE\n"
1307 "#ifdef MODE_LIGHTDIRECTION\n"
1308 " // directional model lighting\n"
1309 "# ifdef USEDIFFUSE\n"
1310 " // get the light normal\n"
1311 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1313 "# ifdef USESPECULAR\n"
1314 " // calculate directional shading\n"
1315 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1316 "# ifdef USEEXACTSPECULARMATH\n"
1317 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1319 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1320 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1323 "# ifdef USEDIFFUSE\n"
1325 " // calculate directional shading\n"
1326 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1328 " color.rgb *= AmbientColor;\n"
1331 "#endif // MODE_LIGHTDIRECTION\n"
1336 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1337 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1339 " // get the light normal\n"
1340 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1341 " myhalf3 diffusenormal;\n"
1342 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1343 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1344 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1345 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1346 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1347 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1348 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1349 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1350 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1351 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1352 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1353 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1354 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1355 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1356 "# ifdef USESPECULAR\n"
1357 "# ifdef USEEXACTSPECULARMATH\n"
1358 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1360 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1361 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1365 " // apply lightmap color\n"
1366 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1367 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1372 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1373 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1375 " // get the light normal\n"
1376 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1377 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1378 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1379 "# ifdef USESPECULAR\n"
1380 "# ifdef USEEXACTSPECULARMATH\n"
1381 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1383 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1384 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1388 " // apply lightmap color\n"
1389 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1390 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1395 "#ifdef MODE_LIGHTMAP\n"
1396 " // apply lightmap color\n"
1397 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1398 "#endif // MODE_LIGHTMAP\n"
1403 "#ifdef MODE_VERTEXCOLOR\n"
1404 " // apply lightmap color\n"
1405 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1406 "#endif // MODE_VERTEXCOLOR\n"
1411 "#ifdef MODE_FLATCOLOR\n"
1412 "#endif // MODE_FLATCOLOR\n"
1420 " color *= TintColor;\n"
1423 "#ifdef USEVERTEXTEXTUREBLEND\n"
1424 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1426 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1430 " color.rgb *= SceneBrightness;\n"
1432 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1435 "#ifdef USEFOGOUTSIDE\n"
1436 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1438 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1440 "// float FogHeightFade1 = -0.5/1024.0;\n"
1441 "// if (FogPlaneViewDist >= 0.0)\n"
1442 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade1);\n"
1444 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade1);\n"
1445 "//# ifdef USEFOGABOVE\n"
1446 "// if (FogPlaneViewDist >= 0.0)\n"
1447 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist);\n"
1449 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist));\n"
1450 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1451 "// fogfrac *= min(1.0, (max(0.0, fade*FogPlaneVertexDist) + max(0.0, fade*FogPlaneViewDist)));\n"
1452 "// fogfrac *= min(1.0, (max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1453 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1455 " //fogfrac *= min(1.0, max(0.0, (max(-2048, min(0, FogPlaneVertexDist)) + max(-2048, min(0, FogPlaneViewDist)))/-2048.0));\n"
1456 " //float fade = -0.5/128.0;\n"
1457 " //fogfrac *= max(0.0, min(1.0, fade*FogPlaneVertexDist)) + max(0.0, min(1.0, fade*FogPlaneViewDist));\n"
1458 " //fogfrac *= max(0.0, min(1.0, FogHeightFade1*FogPlaneVertexDist)) + max(0.0, min(1.0, FogHeightFade1*FogPlaneViewDist));\n"
1459 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1460 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1461 " //fogfrac *= min(1.0, min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1462 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1463 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1464 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1466 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0))));\n"
1469 " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1470 "#ifdef USEREFLECTION\n"
1471 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1472 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1473 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1474 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1475 " // FIXME temporary hack to detect the case that the reflection\n"
1476 " // gets blackened at edges due to leaving the area that contains actual\n"
1478 " // Remove this 'ack once we have a better way to stop this thing from\n"
1480 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1481 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1482 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1483 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1484 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1485 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1488 " gl_FragColor = vec4(color);\n"
1490 "#if showshadowmap\n"
1491 "# ifdef USESHADOWMAPRECT\n"
1492 "# ifdef USESHADOWSAMPLER\n"
1493 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1495 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1498 "# ifdef USESHADOWMAP2D\n"
1499 "# ifdef USESHADOWSAMPLER\n"
1500 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1502 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1506 "# ifdef USESHADOWMAPCUBE\n"
1507 "# ifdef USESHADOWSAMPLER\n"
1508 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1510 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1515 "#endif // !MODE_REFRACTION\n"
1516 "#endif // !MODE_WATER\n"
1518 "#endif // FRAGMENT_SHADER\n"
1520 "#endif // !MODE_BLOOMBLUR\n"
1521 "#endif // !MODE_GENERIC\n"
1522 "#endif // !MODE_POSTPROCESS\n"
1523 "#endif // !MODE_SHOWDEPTH\n"
1524 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1527 typedef struct shaderpermutationinfo_s
1529 const char *pretext;
1532 shaderpermutationinfo_t;
1534 typedef struct shadermodeinfo_s
1536 const char *vertexfilename;
1537 const char *geometryfilename;
1538 const char *fragmentfilename;
1539 const char *pretext;
1544 typedef enum shaderpermutation_e
1546 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1547 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1548 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1549 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1550 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1551 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1552 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1553 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1554 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1555 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1556 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1557 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1558 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1559 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1560 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1561 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1562 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1563 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1564 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1565 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1566 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1567 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1568 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1569 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1570 SHADERPERMUTATION_LIMIT = 1<<24, ///< size of permutations array
1571 SHADERPERMUTATION_COUNT = 24 ///< size of shaderpermutationinfo array
1573 shaderpermutation_t;
1575 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1576 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1578 {"#define USEDIFFUSE\n", " diffuse"},
1579 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1580 {"#define USEVIEWTINT\n", " viewtint"},
1581 {"#define USECOLORMAPPING\n", " colormapping"},
1582 {"#define USESATURATION\n", " saturation"},
1583 {"#define USEFOGINSIDE\n", " foginside"},
1584 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1585 {"#define USEGAMMARAMPS\n", " gammaramps"},
1586 {"#define USECUBEFILTER\n", " cubefilter"},
1587 {"#define USEGLOW\n", " glow"},
1588 {"#define USEBLOOM\n", " bloom"},
1589 {"#define USESPECULAR\n", " specular"},
1590 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1591 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1592 {"#define USEREFLECTION\n", " reflection"},
1593 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1594 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1595 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1596 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1597 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1598 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1599 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1600 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1601 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1604 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1605 typedef enum shadermode_e
1607 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1608 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1609 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1610 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1611 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1612 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1613 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1614 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1615 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1616 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1617 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1618 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1619 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1624 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1625 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1627 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1628 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1629 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1630 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1631 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1632 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1633 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1634 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1635 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1636 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1637 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1638 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1639 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1642 struct r_glsl_permutation_s;
1643 typedef struct r_glsl_permutation_s
1645 /// hash lookup data
1646 struct r_glsl_permutation_s *hashnext;
1648 unsigned int permutation;
1650 /// indicates if we have tried compiling this permutation already
1652 /// 0 if compilation failed
1654 /// locations of detected uniforms in program object, or -1 if not found
1655 int loc_Texture_First;
1656 int loc_Texture_Second;
1657 int loc_Texture_GammaRamps;
1658 int loc_Texture_Normal;
1659 int loc_Texture_Color;
1660 int loc_Texture_Gloss;
1661 int loc_Texture_Glow;
1662 int loc_Texture_SecondaryNormal;
1663 int loc_Texture_SecondaryColor;
1664 int loc_Texture_SecondaryGloss;
1665 int loc_Texture_SecondaryGlow;
1666 int loc_Texture_Pants;
1667 int loc_Texture_Shirt;
1668 int loc_Texture_FogMask;
1669 int loc_Texture_Lightmap;
1670 int loc_Texture_Deluxemap;
1671 int loc_Texture_Attenuation;
1672 int loc_Texture_Cube;
1673 int loc_Texture_Refraction;
1674 int loc_Texture_Reflection;
1675 int loc_Texture_ShadowMapRect;
1676 int loc_Texture_ShadowMapCube;
1677 int loc_Texture_ShadowMap2D;
1678 int loc_Texture_CubeProjection;
1680 int loc_LightPosition;
1681 int loc_EyePosition;
1682 int loc_Color_Pants;
1683 int loc_Color_Shirt;
1685 int loc_FogPlaneViewDist;
1686 int loc_FogRangeRecip;
1687 int loc_FogHeightFade;
1688 int loc_AmbientScale;
1689 int loc_DiffuseScale;
1690 int loc_SpecularScale;
1691 int loc_SpecularPower;
1693 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1694 int loc_OffsetMapping_Scale;
1696 int loc_AmbientColor;
1697 int loc_DiffuseColor;
1698 int loc_SpecularColor;
1700 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1701 int loc_GammaCoeff; ///< 1 / gamma
1702 int loc_DistortScaleRefractReflect;
1703 int loc_ScreenScaleRefractReflect;
1704 int loc_ScreenCenterRefractReflect;
1705 int loc_RefractColor;
1706 int loc_ReflectColor;
1707 int loc_ReflectFactor;
1708 int loc_ReflectOffset;
1716 int loc_ShadowMap_TextureScale;
1717 int loc_ShadowMap_Parameters;
1719 r_glsl_permutation_t;
1721 #define SHADERPERMUTATION_HASHSIZE 256
1723 /// information about each possible shader permutation
1724 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1725 /// currently selected permutation
1726 r_glsl_permutation_t *r_glsl_permutation;
1727 /// storage for permutations linked in the hash table
1728 memexpandablearray_t r_glsl_permutationarray;
1730 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1732 //unsigned int hashdepth = 0;
1733 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1734 r_glsl_permutation_t *p;
1735 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1737 if (p->mode == mode && p->permutation == permutation)
1739 //if (hashdepth > 10)
1740 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1745 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1747 p->permutation = permutation;
1748 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1749 r_glsl_permutationhash[mode][hashindex] = p;
1750 //if (hashdepth > 10)
1751 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1755 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1758 if (!filename || !filename[0])
1760 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1763 if (printfromdisknotice)
1764 Con_DPrint("from disk... ");
1765 return shaderstring;
1767 else if (!strcmp(filename, "glsl/default.glsl"))
1769 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1770 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1772 return shaderstring;
1775 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1778 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1779 int vertstrings_count = 0;
1780 int geomstrings_count = 0;
1781 int fragstrings_count = 0;
1782 char *vertexstring, *geometrystring, *fragmentstring;
1783 const char *vertstrings_list[32+3];
1784 const char *geomstrings_list[32+3];
1785 const char *fragstrings_list[32+3];
1786 char permutationname[256];
1793 permutationname[0] = 0;
1794 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1795 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1796 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1798 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1800 // the first pretext is which type of shader to compile as
1801 // (later these will all be bound together as a program object)
1802 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1803 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1804 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1806 // the second pretext is the mode (for example a light source)
1807 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1808 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1809 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1810 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1812 // now add all the permutation pretexts
1813 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1815 if (permutation & (1<<i))
1817 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1818 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1819 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1820 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1824 // keep line numbers correct
1825 vertstrings_list[vertstrings_count++] = "\n";
1826 geomstrings_list[geomstrings_count++] = "\n";
1827 fragstrings_list[fragstrings_count++] = "\n";
1831 // now append the shader text itself
1832 vertstrings_list[vertstrings_count++] = vertexstring;
1833 geomstrings_list[geomstrings_count++] = geometrystring;
1834 fragstrings_list[fragstrings_count++] = fragmentstring;
1836 // if any sources were NULL, clear the respective list
1838 vertstrings_count = 0;
1839 if (!geometrystring)
1840 geomstrings_count = 0;
1841 if (!fragmentstring)
1842 fragstrings_count = 0;
1844 // compile the shader program
1845 if (vertstrings_count + geomstrings_count + fragstrings_count)
1846 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1850 qglUseProgramObjectARB(p->program);CHECKGLERROR
1851 // look up all the uniform variable names we care about, so we don't
1852 // have to look them up every time we set them
1853 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1854 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1855 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1856 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1857 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1858 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1859 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1860 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1861 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1862 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1863 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1864 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1865 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1866 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1867 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1868 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1869 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1870 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1871 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1872 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1873 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1874 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1875 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1876 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1877 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1878 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1879 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1880 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1881 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1882 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
1883 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
1884 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1885 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
1886 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1887 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1888 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1889 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1890 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1891 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1892 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1893 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1894 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1895 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1896 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1897 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1898 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1899 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1900 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1901 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1902 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1903 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1904 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1905 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1906 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1907 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1908 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1909 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1910 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1911 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1912 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1913 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1914 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1915 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1916 // initialize the samplers to refer to the texture units we use
1917 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1918 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1919 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1920 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1921 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1922 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1923 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1924 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1925 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1926 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1927 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1928 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1929 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1930 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1931 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1932 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1933 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1934 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1935 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1936 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1937 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1938 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1939 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1940 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1942 if (developer.integer)
1943 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1946 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1950 Mem_Free(vertexstring);
1952 Mem_Free(geometrystring);
1954 Mem_Free(fragmentstring);
1957 void R_GLSL_Restart_f(void)
1959 unsigned int i, limit;
1960 r_glsl_permutation_t *p;
1961 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1962 for (i = 0;i < limit;i++)
1964 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1966 GL_Backend_FreeProgram(p->program);
1967 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1970 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1973 void R_GLSL_DumpShader_f(void)
1977 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1980 Con_Printf("failed to write to glsl/default.glsl\n");
1984 FS_Print(file, "/* The engine may define the following macros:\n");
1985 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1986 for (i = 0;i < SHADERMODE_COUNT;i++)
1987 FS_Print(file, shadermodeinfo[i].pretext);
1988 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1989 FS_Print(file, shaderpermutationinfo[i].pretext);
1990 FS_Print(file, "*/\n");
1991 FS_Print(file, builtinshaderstring);
1994 Con_Printf("glsl/default.glsl written\n");
1997 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1999 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2000 if (r_glsl_permutation != perm)
2002 r_glsl_permutation = perm;
2003 if (!r_glsl_permutation->program)
2005 if (!r_glsl_permutation->compiled)
2006 R_GLSL_CompilePermutation(perm, mode, permutation);
2007 if (!r_glsl_permutation->program)
2009 // remove features until we find a valid permutation
2011 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2013 // reduce i more quickly whenever it would not remove any bits
2014 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2015 if (!(permutation & j))
2018 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2019 if (!r_glsl_permutation->compiled)
2020 R_GLSL_CompilePermutation(perm, mode, permutation);
2021 if (r_glsl_permutation->program)
2024 if (i >= SHADERPERMUTATION_COUNT)
2026 Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
2027 Cvar_SetValueQuick(&r_glsl, 0);
2028 R_GLSL_Restart_f(); // unload shaders
2029 return; // no bit left to clear
2034 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2038 void R_SetupGenericShader(qboolean usetexture)
2040 if (gl_support_fragment_shader)
2042 if (r_glsl.integer && r_glsl_usegeneric.integer)
2043 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2044 else if (r_glsl_permutation)
2046 r_glsl_permutation = NULL;
2047 qglUseProgramObjectARB(0);CHECKGLERROR
2052 void R_SetupGenericTwoTextureShader(int texturemode)
2054 if (gl_support_fragment_shader)
2056 if (r_glsl.integer && r_glsl_usegeneric.integer)
2057 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
2058 else if (r_glsl_permutation)
2060 r_glsl_permutation = NULL;
2061 qglUseProgramObjectARB(0);CHECKGLERROR
2064 if (!r_glsl_permutation)
2066 if (texturemode == GL_DECAL && gl_combine.integer)
2067 texturemode = GL_INTERPOLATE_ARB;
2068 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
2072 void R_SetupDepthOrShadowShader(void)
2074 if (gl_support_fragment_shader)
2076 if (r_glsl.integer && r_glsl_usegeneric.integer)
2077 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2078 else if (r_glsl_permutation)
2080 r_glsl_permutation = NULL;
2081 qglUseProgramObjectARB(0);CHECKGLERROR
2086 void R_SetupShowDepthShader(void)
2088 if (gl_support_fragment_shader)
2090 if (r_glsl.integer && r_glsl_usegeneric.integer)
2091 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2092 else if (r_glsl_permutation)
2094 r_glsl_permutation = NULL;
2095 qglUseProgramObjectARB(0);CHECKGLERROR
2100 extern rtexture_t *r_shadow_attenuationgradienttexture;
2101 extern rtexture_t *r_shadow_attenuation2dtexture;
2102 extern rtexture_t *r_shadow_attenuation3dtexture;
2103 extern qboolean r_shadow_usingshadowmaprect;
2104 extern qboolean r_shadow_usingshadowmapcube;
2105 extern qboolean r_shadow_usingshadowmap2d;
2106 extern float r_shadow_shadowmap_texturescale[2];
2107 extern float r_shadow_shadowmap_parameters[4];
2108 extern qboolean r_shadow_shadowmapvsdct;
2109 extern qboolean r_shadow_shadowmapsampler;
2110 extern int r_shadow_shadowmappcf;
2111 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2113 // select a permutation of the lighting shader appropriate to this
2114 // combination of texture, entity, light source, and fogging, only use the
2115 // minimum features necessary to avoid wasting rendering time in the
2116 // fragment shader on features that are not being used
2117 unsigned int permutation = 0;
2118 unsigned int mode = 0;
2119 // TODO: implement geometry-shader based shadow volumes someday
2120 if (r_glsl_offsetmapping.integer)
2122 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2123 if (r_glsl_offsetmapping_reliefmapping.integer)
2124 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2126 if (rsurfacepass == RSURFPASS_BACKGROUND)
2128 // distorted background
2129 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2130 mode = SHADERMODE_WATER;
2132 mode = SHADERMODE_REFRACTION;
2134 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2137 mode = SHADERMODE_LIGHTSOURCE;
2138 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2139 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2140 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2141 permutation |= SHADERPERMUTATION_CUBEFILTER;
2142 if (diffusescale > 0)
2143 permutation |= SHADERPERMUTATION_DIFFUSE;
2144 if (specularscale > 0)
2145 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2146 if (r_refdef.fogenabled)
2147 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2148 if (rsurface.texture->colormapping)
2149 permutation |= SHADERPERMUTATION_COLORMAPPING;
2150 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2152 if (r_shadow_usingshadowmaprect)
2153 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2154 if (r_shadow_usingshadowmap2d)
2155 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2156 if (r_shadow_usingshadowmapcube)
2157 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2158 else if(r_shadow_shadowmapvsdct)
2159 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2161 if (r_shadow_shadowmapsampler)
2162 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2163 if (r_shadow_shadowmappcf > 1)
2164 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2165 else if (r_shadow_shadowmappcf)
2166 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2169 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2171 // unshaded geometry (fullbright or ambient model lighting)
2172 mode = SHADERMODE_FLATCOLOR;
2173 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2174 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2175 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2176 permutation |= SHADERPERMUTATION_GLOW;
2177 if (r_refdef.fogenabled)
2178 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2179 if (rsurface.texture->colormapping)
2180 permutation |= SHADERPERMUTATION_COLORMAPPING;
2181 if (r_glsl_offsetmapping.integer)
2183 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2184 if (r_glsl_offsetmapping_reliefmapping.integer)
2185 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2187 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2188 permutation |= SHADERPERMUTATION_REFLECTION;
2190 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2192 // directional model lighting
2193 mode = SHADERMODE_LIGHTDIRECTION;
2194 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2195 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2196 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2197 permutation |= SHADERPERMUTATION_GLOW;
2198 permutation |= SHADERPERMUTATION_DIFFUSE;
2199 if (specularscale > 0)
2200 permutation |= SHADERPERMUTATION_SPECULAR;
2201 if (r_refdef.fogenabled)
2202 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2203 if (rsurface.texture->colormapping)
2204 permutation |= SHADERPERMUTATION_COLORMAPPING;
2205 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2206 permutation |= SHADERPERMUTATION_REFLECTION;
2208 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2210 // ambient model lighting
2211 mode = SHADERMODE_LIGHTDIRECTION;
2212 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2213 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2214 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2215 permutation |= SHADERPERMUTATION_GLOW;
2216 if (r_refdef.fogenabled)
2217 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2218 if (rsurface.texture->colormapping)
2219 permutation |= SHADERPERMUTATION_COLORMAPPING;
2220 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2221 permutation |= SHADERPERMUTATION_REFLECTION;
2226 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2228 // deluxemapping (light direction texture)
2229 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2230 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2232 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2233 permutation |= SHADERPERMUTATION_DIFFUSE;
2234 if (specularscale > 0)
2235 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2237 else if (r_glsl_deluxemapping.integer >= 2)
2239 // fake deluxemapping (uniform light direction in tangentspace)
2240 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2241 permutation |= SHADERPERMUTATION_DIFFUSE;
2242 if (specularscale > 0)
2243 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2245 else if (rsurface.uselightmaptexture)
2247 // ordinary lightmapping (q1bsp, q3bsp)
2248 mode = SHADERMODE_LIGHTMAP;
2252 // ordinary vertex coloring (q3bsp)
2253 mode = SHADERMODE_VERTEXCOLOR;
2255 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2256 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2257 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258 permutation |= SHADERPERMUTATION_GLOW;
2259 if (r_refdef.fogenabled)
2260 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2261 if (rsurface.texture->colormapping)
2262 permutation |= SHADERPERMUTATION_COLORMAPPING;
2263 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2264 permutation |= SHADERPERMUTATION_REFLECTION;
2266 if(permutation & SHADERPERMUTATION_SPECULAR)
2267 if(r_shadow_glossexact.integer)
2268 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2269 R_SetupShader_SetPermutation(mode, permutation);
2270 if (mode == SHADERMODE_LIGHTSOURCE)
2272 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2273 if (permutation & SHADERPERMUTATION_DIFFUSE)
2275 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2276 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2277 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2278 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2282 // ambient only is simpler
2283 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
2284 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2285 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2286 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2288 // additive passes are only darkened by fog, not tinted
2289 if (r_glsl_permutation->loc_FogColor >= 0)
2290 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2291 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2292 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2296 if (mode == SHADERMODE_LIGHTDIRECTION)
2298 if (r_glsl_permutation->loc_AmbientColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale * 0.5f, rsurface.modellight_ambient[1] * ambientscale * 0.5f, rsurface.modellight_ambient[2] * ambientscale * 0.5f);
2299 if (r_glsl_permutation->loc_DiffuseColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale * 0.5f, rsurface.modellight_diffuse[1] * diffusescale * 0.5f, rsurface.modellight_diffuse[2] * diffusescale * 0.5f);
2300 if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
2301 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2305 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2306 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2307 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2309 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
2310 if (r_glsl_permutation->loc_GlowColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_GlowColor, rsurface.glowmod[0] * r_hdr_glowintensity.value, rsurface.glowmod[1] * r_hdr_glowintensity.value, rsurface.glowmod[2] * r_hdr_glowintensity.value);
2311 // additive passes are only darkened by fog, not tinted
2312 if (r_glsl_permutation->loc_FogColor >= 0)
2314 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2315 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2317 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2319 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2320 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2321 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2322 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2323 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2324 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2325 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2327 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2328 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2329 if (r_glsl_permutation->loc_Color_Pants >= 0)
2331 if (rsurface.texture->currentskinframe->pants)
2332 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2334 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2336 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2338 if (rsurface.texture->currentskinframe->shirt)
2339 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2341 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2343 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2344 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2345 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2346 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2347 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2349 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2353 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2355 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2359 #define SKINFRAME_HASH 1024
2363 int loadsequence; // incremented each level change
2364 memexpandablearray_t array;
2365 skinframe_t *hash[SKINFRAME_HASH];
2368 r_skinframe_t r_skinframe;
2370 void R_SkinFrame_PrepareForPurge(void)
2372 r_skinframe.loadsequence++;
2373 // wrap it without hitting zero
2374 if (r_skinframe.loadsequence >= 200)
2375 r_skinframe.loadsequence = 1;
2378 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2382 // mark the skinframe as used for the purging code
2383 skinframe->loadsequence = r_skinframe.loadsequence;
2386 void R_SkinFrame_Purge(void)
2390 for (i = 0;i < SKINFRAME_HASH;i++)
2392 for (s = r_skinframe.hash[i];s;s = s->next)
2394 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2396 if (s->merged == s->base)
2398 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2399 R_PurgeTexture(s->stain );s->stain = NULL;
2400 R_PurgeTexture(s->merged);s->merged = NULL;
2401 R_PurgeTexture(s->base );s->base = NULL;
2402 R_PurgeTexture(s->pants );s->pants = NULL;
2403 R_PurgeTexture(s->shirt );s->shirt = NULL;
2404 R_PurgeTexture(s->nmap );s->nmap = NULL;
2405 R_PurgeTexture(s->gloss );s->gloss = NULL;
2406 R_PurgeTexture(s->glow );s->glow = NULL;
2407 R_PurgeTexture(s->fog );s->fog = NULL;
2408 s->loadsequence = 0;
2414 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2416 char basename[MAX_QPATH];
2418 Image_StripImageExtension(name, basename, sizeof(basename));
2420 if( last == NULL ) {
2422 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2423 item = r_skinframe.hash[hashindex];
2428 // linearly search through the hash bucket
2429 for( ; item ; item = item->next ) {
2430 if( !strcmp( item->basename, basename ) ) {
2437 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2441 char basename[MAX_QPATH];
2443 Image_StripImageExtension(name, basename, sizeof(basename));
2445 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2446 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2447 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2451 rtexture_t *dyntexture;
2452 // check whether its a dynamic texture
2453 dyntexture = CL_GetDynTexture( basename );
2454 if (!add && !dyntexture)
2456 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2457 memset(item, 0, sizeof(*item));
2458 strlcpy(item->basename, basename, sizeof(item->basename));
2459 item->base = dyntexture; // either NULL or dyntexture handle
2460 item->textureflags = textureflags;
2461 item->comparewidth = comparewidth;
2462 item->compareheight = compareheight;
2463 item->comparecrc = comparecrc;
2464 item->next = r_skinframe.hash[hashindex];
2465 r_skinframe.hash[hashindex] = item;
2467 else if( item->base == NULL )
2469 rtexture_t *dyntexture;
2470 // check whether its a dynamic texture
2471 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
2472 dyntexture = CL_GetDynTexture( basename );
2473 item->base = dyntexture; // either NULL or dyntexture handle
2476 R_SkinFrame_MarkUsed(item);
2480 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2482 unsigned long long avgcolor[5], wsum; \
2490 for(pix = 0; pix < cnt; ++pix) \
2493 for(comp = 0; comp < 3; ++comp) \
2495 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2498 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2500 for(comp = 0; comp < 3; ++comp) \
2501 avgcolor[comp] += getpixel * w; \
2504 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2505 avgcolor[4] += getpixel; \
2507 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2509 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2510 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2511 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2512 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2515 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2517 // FIXME: it should be possible to disable loading various layers using
2518 // cvars, to prevent wasted loading time and memory usage if the user does
2520 qboolean loadnormalmap = true;
2521 qboolean loadgloss = true;
2522 qboolean loadpantsandshirt = true;
2523 qboolean loadglow = true;
2525 unsigned char *pixels;
2526 unsigned char *bumppixels;
2527 unsigned char *basepixels = NULL;
2528 int basepixels_width;
2529 int basepixels_height;
2530 skinframe_t *skinframe;
2535 if (cls.state == ca_dedicated)
2538 // return an existing skinframe if already loaded
2539 // if loading of the first image fails, don't make a new skinframe as it
2540 // would cause all future lookups of this to be missing
2541 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2542 if (skinframe && skinframe->base)
2545 basepixels = loadimagepixelsbgra(name, complain, true);
2546 if (basepixels == NULL)
2549 if (developer_loading.integer)
2550 Con_Printf("loading skin \"%s\"\n", name);
2552 // we've got some pixels to store, so really allocate this new texture now
2554 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2555 skinframe->stain = NULL;
2556 skinframe->merged = NULL;
2557 skinframe->base = r_texture_notexture;
2558 skinframe->pants = NULL;
2559 skinframe->shirt = NULL;
2560 skinframe->nmap = r_texture_blanknormalmap;
2561 skinframe->gloss = NULL;
2562 skinframe->glow = NULL;
2563 skinframe->fog = NULL;
2565 basepixels_width = image_width;
2566 basepixels_height = image_height;
2567 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2569 if (textureflags & TEXF_ALPHA)
2571 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2572 if (basepixels[j] < 255)
2574 if (j < basepixels_width * basepixels_height * 4)
2576 // has transparent pixels
2579 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2580 for (j = 0;j < image_width * image_height * 4;j += 4)
2585 pixels[j+3] = basepixels[j+3];
2587 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2592 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2593 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2595 // _norm is the name used by tenebrae and has been adopted as standard
2598 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2600 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2604 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2606 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2607 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2608 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2610 Mem_Free(bumppixels);
2612 else if (r_shadow_bumpscale_basetexture.value > 0)
2614 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2615 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2616 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2620 // _luma is supported for tenebrae compatibility
2621 // (I think it's a very stupid name, but oh well)
2622 // _glow is the preferred name
2623 if (loadglow && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2624 if (loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2625 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2626 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2629 Mem_Free(basepixels);
2634 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2636 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, NULL);
2639 static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
2644 for (i = 0;i < width*height;i++)
2645 if (((unsigned char *)&palette[in[i]])[3] > 0)
2647 if (i == width*height)
2650 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2653 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2654 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2657 unsigned char *temp1, *temp2;
2658 skinframe_t *skinframe;
2660 if (cls.state == ca_dedicated)
2663 // if already loaded just return it, otherwise make a new skinframe
2664 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2665 if (skinframe && skinframe->base)
2668 skinframe->stain = NULL;
2669 skinframe->merged = NULL;
2670 skinframe->base = r_texture_notexture;
2671 skinframe->pants = NULL;
2672 skinframe->shirt = NULL;
2673 skinframe->nmap = r_texture_blanknormalmap;
2674 skinframe->gloss = NULL;
2675 skinframe->glow = NULL;
2676 skinframe->fog = NULL;
2678 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2682 if (developer_loading.integer)
2683 Con_Printf("loading 32bit skin \"%s\"\n", name);
2685 if (r_shadow_bumpscale_basetexture.value > 0)
2687 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2688 temp2 = temp1 + width * height * 4;
2689 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2690 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2693 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2694 if (textureflags & TEXF_ALPHA)
2696 for (i = 3;i < width * height * 4;i += 4)
2697 if (skindata[i] < 255)
2699 if (i < width * height * 4)
2701 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2702 memcpy(fogpixels, skindata, width * height * 4);
2703 for (i = 0;i < width * height * 4;i += 4)
2704 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2705 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2706 Mem_Free(fogpixels);
2710 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2711 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2716 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2719 unsigned char *temp1, *temp2;
2720 unsigned int *palette;
2721 skinframe_t *skinframe;
2723 if (cls.state == ca_dedicated)
2726 // if already loaded just return it, otherwise make a new skinframe
2727 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2728 if (skinframe && skinframe->base)
2731 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2733 skinframe->stain = NULL;
2734 skinframe->merged = NULL;
2735 skinframe->base = r_texture_notexture;
2736 skinframe->pants = NULL;
2737 skinframe->shirt = NULL;
2738 skinframe->nmap = r_texture_blanknormalmap;
2739 skinframe->gloss = NULL;
2740 skinframe->glow = NULL;
2741 skinframe->fog = NULL;
2743 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2747 if (developer_loading.integer)
2748 Con_Printf("loading quake skin \"%s\"\n", name);
2750 if (r_shadow_bumpscale_basetexture.value > 0)
2752 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2753 temp2 = temp1 + width * height * 4;
2754 // use either a custom palette or the quake palette
2755 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2756 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2757 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2760 // use either a custom palette, or the quake palette
2761 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2762 if (loadglowtexture)
2763 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2764 if (loadpantsandshirt)
2766 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2767 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2769 if (skinframe->pants || skinframe->shirt)
2770 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors
2771 if (textureflags & TEXF_ALPHA)
2773 for (i = 0;i < width * height;i++)
2774 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2776 if (i < width * height)
2777 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2780 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2781 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2786 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
2789 skinframe_t *skinframe;
2791 if (cls.state == ca_dedicated)
2794 // if already loaded just return it, otherwise make a new skinframe
2795 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2796 if (skinframe && skinframe->base)
2799 skinframe->stain = NULL;
2800 skinframe->merged = NULL;
2801 skinframe->base = r_texture_notexture;
2802 skinframe->pants = NULL;
2803 skinframe->shirt = NULL;
2804 skinframe->nmap = r_texture_blanknormalmap;
2805 skinframe->gloss = NULL;
2806 skinframe->glow = NULL;
2807 skinframe->fog = NULL;
2809 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2813 if (developer_loading.integer)
2814 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2816 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, skinframe->basename, palette, skinframe->textureflags, true);
2817 if (textureflags & TEXF_ALPHA)
2819 for (i = 0;i < width * height;i++)
2820 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
2822 if (i < width * height)
2823 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
2826 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2827 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2832 skinframe_t *R_SkinFrame_LoadMissing(void)
2834 skinframe_t *skinframe;
2836 if (cls.state == ca_dedicated)
2839 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2840 skinframe->stain = NULL;
2841 skinframe->merged = NULL;
2842 skinframe->base = r_texture_notexture;
2843 skinframe->pants = NULL;
2844 skinframe->shirt = NULL;
2845 skinframe->nmap = r_texture_blanknormalmap;
2846 skinframe->gloss = NULL;
2847 skinframe->glow = NULL;
2848 skinframe->fog = NULL;
2850 skinframe->avgcolor[0] = rand() / RAND_MAX;
2851 skinframe->avgcolor[1] = rand() / RAND_MAX;
2852 skinframe->avgcolor[2] = rand() / RAND_MAX;
2853 skinframe->avgcolor[3] = 1;
2858 void R_Main_FreeViewCache(void)
2860 if (r_refdef.viewcache.entityvisible)
2861 Mem_Free(r_refdef.viewcache.entityvisible);
2862 if (r_refdef.viewcache.world_pvsbits)
2863 Mem_Free(r_refdef.viewcache.world_pvsbits);
2864 if (r_refdef.viewcache.world_leafvisible)
2865 Mem_Free(r_refdef.viewcache.world_leafvisible);
2866 if (r_refdef.viewcache.world_surfacevisible)
2867 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2868 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2871 void R_Main_ResizeViewCache(void)
2873 int numentities = r_refdef.scene.numentities;
2874 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
2875 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
2876 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
2877 if (r_refdef.viewcache.maxentities < numentities)
2879 r_refdef.viewcache.maxentities = numentities;
2880 if (r_refdef.viewcache.entityvisible)
2881 Mem_Free(r_refdef.viewcache.entityvisible);
2882 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
2884 if (r_refdef.viewcache.world_numclusters != numclusters)
2886 r_refdef.viewcache.world_numclusters = numclusters;
2887 if (r_refdef.viewcache.world_pvsbits)
2888 Mem_Free(r_refdef.viewcache.world_pvsbits);
2889 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, (r_refdef.viewcache.world_numclusters+7)>>3);
2891 if (r_refdef.viewcache.world_numleafs != numleafs)
2893 r_refdef.viewcache.world_numleafs = numleafs;
2894 if (r_refdef.viewcache.world_leafvisible)
2895 Mem_Free(r_refdef.viewcache.world_leafvisible);
2896 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
2898 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
2900 r_refdef.viewcache.world_numsurfaces = numsurfaces;
2901 if (r_refdef.viewcache.world_surfacevisible)
2902 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2903 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
2907 void gl_main_start(void)
2911 memset(r_queries, 0, sizeof(r_queries));
2913 r_qwskincache = NULL;
2914 r_qwskincache_size = 0;
2916 // set up r_skinframe loading system for textures
2917 memset(&r_skinframe, 0, sizeof(r_skinframe));
2918 r_skinframe.loadsequence = 1;
2919 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2921 r_main_texturepool = R_AllocTexturePool();
2922 R_BuildBlankTextures();
2924 if (gl_texturecubemap)
2927 R_BuildNormalizationCube();
2929 r_texture_fogattenuation = NULL;
2930 r_texture_gammaramps = NULL;
2931 //r_texture_fogintensity = NULL;
2932 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2933 memset(&r_waterstate, 0, sizeof(r_waterstate));
2934 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2935 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2936 memset(&r_svbsp, 0, sizeof (r_svbsp));
2938 r_refdef.fogmasktable_density = 0;
2941 extern rtexture_t *loadingscreentexture;
2942 void gl_main_shutdown(void)
2944 R_Main_FreeViewCache();
2947 qglDeleteQueriesARB(r_maxqueries, r_queries);
2951 memset(r_queries, 0, sizeof(r_queries));
2953 r_qwskincache = NULL;
2954 r_qwskincache_size = 0;
2956 // clear out the r_skinframe state
2957 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2958 memset(&r_skinframe, 0, sizeof(r_skinframe));
2961 Mem_Free(r_svbsp.nodes);
2962 memset(&r_svbsp, 0, sizeof (r_svbsp));
2963 R_FreeTexturePool(&r_main_texturepool);
2964 loadingscreentexture = NULL;
2965 r_texture_blanknormalmap = NULL;
2966 r_texture_white = NULL;
2967 r_texture_grey128 = NULL;
2968 r_texture_black = NULL;
2969 r_texture_whitecube = NULL;
2970 r_texture_normalizationcube = NULL;
2971 r_texture_fogattenuation = NULL;
2972 r_texture_gammaramps = NULL;
2973 //r_texture_fogintensity = NULL;
2974 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2975 memset(&r_waterstate, 0, sizeof(r_waterstate));
2979 extern void CL_ParseEntityLump(char *entitystring);
2980 void gl_main_newmap(void)
2982 // FIXME: move this code to client
2984 char *entities, entname[MAX_QPATH];
2986 Mem_Free(r_qwskincache);
2987 r_qwskincache = NULL;
2988 r_qwskincache_size = 0;
2991 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2992 l = (int)strlen(entname) - 4;
2993 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2995 memcpy(entname + l, ".ent", 5);
2996 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2998 CL_ParseEntityLump(entities);
3003 if (cl.worldmodel->brush.entities)
3004 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3006 R_Main_FreeViewCache();
3009 void GL_Main_Init(void)
3011 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3013 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3014 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3015 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3016 if (gamemode == GAME_NEHAHRA)
3018 Cvar_RegisterVariable (&gl_fogenable);
3019 Cvar_RegisterVariable (&gl_fogdensity);
3020 Cvar_RegisterVariable (&gl_fogred);
3021 Cvar_RegisterVariable (&gl_foggreen);
3022 Cvar_RegisterVariable (&gl_fogblue);
3023 Cvar_RegisterVariable (&gl_fogstart);
3024 Cvar_RegisterVariable (&gl_fogend);
3025 Cvar_RegisterVariable (&gl_skyclip);
3027 Cvar_RegisterVariable(&r_motionblur);
3028 Cvar_RegisterVariable(&r_motionblur_maxblur);
3029 Cvar_RegisterVariable(&r_motionblur_bmin);
3030 Cvar_RegisterVariable(&r_motionblur_vmin);
3031 Cvar_RegisterVariable(&r_motionblur_vmax);
3032 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3033 Cvar_RegisterVariable(&r_motionblur_randomize);
3034 Cvar_RegisterVariable(&r_damageblur);
3035 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3036 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3037 Cvar_RegisterVariable(&r_equalize_entities_by);
3038 Cvar_RegisterVariable(&r_equalize_entities_to);
3039 Cvar_RegisterVariable(&r_animcache);
3040 Cvar_RegisterVariable(&r_depthfirst);
3041 Cvar_RegisterVariable(&r_useinfinitefarclip);
3042 Cvar_RegisterVariable(&r_farclip_base);
3043 Cvar_RegisterVariable(&r_farclip_world);
3044 Cvar_RegisterVariable(&r_nearclip);
3045 Cvar_RegisterVariable(&r_showbboxes);
3046 Cvar_RegisterVariable(&r_showsurfaces);
3047 Cvar_RegisterVariable(&r_showtris);
3048 Cvar_RegisterVariable(&r_shownormals);
3049 Cvar_RegisterVariable(&r_showlighting);
3050 Cvar_RegisterVariable(&r_showshadowvolumes);
3051 Cvar_RegisterVariable(&r_showcollisionbrushes);
3052 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3053 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3054 Cvar_RegisterVariable(&r_showdisabledepthtest);
3055 Cvar_RegisterVariable(&r_drawportals);
3056 Cvar_RegisterVariable(&r_drawentities);
3057 Cvar_RegisterVariable(&r_cullentities_trace);
3058 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3059 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3060 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3061 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3062 Cvar_RegisterVariable(&r_drawviewmodel);
3063 Cvar_RegisterVariable(&r_speeds);
3064 Cvar_RegisterVariable(&r_fullbrights);
3065 Cvar_RegisterVariable(&r_wateralpha);
3066 Cvar_RegisterVariable(&r_dynamic);
3067 Cvar_RegisterVariable(&r_fullbright);
3068 Cvar_RegisterVariable(&r_shadows);
3069 Cvar_RegisterVariable(&r_shadows_darken);
3070 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3071 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3072 Cvar_RegisterVariable(&r_shadows_throwdistance);
3073 Cvar_RegisterVariable(&r_shadows_throwdirection);
3074 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3075 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3076 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3077 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3078 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3079 Cvar_RegisterVariable(&r_fog_exp2);
3080 Cvar_RegisterVariable(&r_drawfog);
3081 Cvar_RegisterVariable(&r_textureunits);
3082 Cvar_RegisterVariable(&r_glsl);
3083 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3084 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3085 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3086 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3087 Cvar_RegisterVariable(&r_glsl_postprocess);
3088 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3089 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3090 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3091 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3092 Cvar_RegisterVariable(&r_glsl_usegeneric);
3093 Cvar_RegisterVariable(&r_water);
3094 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3095 Cvar_RegisterVariable(&r_water_clippingplanebias);
3096 Cvar_RegisterVariable(&r_water_refractdistort);
3097 Cvar_RegisterVariable(&r_water_reflectdistort);
3098 Cvar_RegisterVariable(&r_lerpsprites);
3099 Cvar_RegisterVariable(&r_lerpmodels);
3100 Cvar_RegisterVariable(&r_lerplightstyles);
3101 Cvar_RegisterVariable(&r_waterscroll);
3102 Cvar_RegisterVariable(&r_bloom);
3103 Cvar_RegisterVariable(&r_bloom_colorscale);
3104 Cvar_RegisterVariable(&r_bloom_brighten);
3105 Cvar_RegisterVariable(&r_bloom_blur);
3106 Cvar_RegisterVariable(&r_bloom_resolution);
3107 Cvar_RegisterVariable(&r_bloom_colorexponent);
3108 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3109 Cvar_RegisterVariable(&r_hdr);
3110 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3111 Cvar_RegisterVariable(&r_hdr_glowintensity);
3112 Cvar_RegisterVariable(&r_hdr_range);
3113 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3114 Cvar_RegisterVariable(&developer_texturelogging);
3115 Cvar_RegisterVariable(&gl_lightmaps);
3116 Cvar_RegisterVariable(&r_test);
3117 Cvar_RegisterVariable(&r_batchmode);
3118 Cvar_RegisterVariable(&r_glsl_saturation);
3119 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3120 Cvar_SetValue("r_fullbrights", 0);
3121 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3123 Cvar_RegisterVariable(&r_track_sprites);
3124 Cvar_RegisterVariable(&r_track_sprites_flags);
3125 Cvar_RegisterVariable(&r_track_sprites_scalew);
3126 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3129 extern void R_Textures_Init(void);
3130 extern void GL_Draw_Init(void);
3131 extern void GL_Main_Init(void);
3132 extern void R_Shadow_Init(void);
3133 extern void R_Sky_Init(void);
3134 extern void GL_Surf_Init(void);
3135 extern void R_Particles_Init(void);
3136 extern void R_Explosion_Init(void);
3137 extern void gl_backend_init(void);
3138 extern void Sbar_Init(void);
3139 extern void R_LightningBeams_Init(void);
3140 extern void Mod_RenderInit(void);
3142 void Render_Init(void)
3154 R_LightningBeams_Init();
3163 extern char *ENGINE_EXTENSIONS;
3166 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3167 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3168 gl_version = (const char *)qglGetString(GL_VERSION);
3169 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3173 if (!gl_platformextensions)
3174 gl_platformextensions = "";
3176 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3177 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3178 Con_Printf("GL_VERSION: %s\n", gl_version);
3179 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3180 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3182 VID_CheckExtensions();
3184 // LordHavoc: report supported extensions
3185 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3187 // clear to black (loading plaque will be seen over this)
3189 qglClearColor(0,0,0,1);CHECKGLERROR
3190 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3193 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3197 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3199 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3202 p = r_refdef.view.frustum + i;
3207 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3211 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3215 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3219 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3223 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3227 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3231 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3235 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3243 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3247 for (i = 0;i < numplanes;i++)
3254 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3258 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3262 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3266 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3270 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3274 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3278 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3282 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3290 //==================================================================================
3292 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3295 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3296 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3297 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3300 typedef struct r_animcache_entity_s
3307 qboolean wantnormals;
3308 qboolean wanttangents;
3310 r_animcache_entity_t;
3312 typedef struct r_animcache_s
3314 r_animcache_entity_t entity[MAX_EDICTS];
3320 static r_animcache_t r_animcachestate;
3322 void R_AnimCache_Free(void)
3325 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3327 r_animcachestate.entity[idx].maxvertices = 0;
3328 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3329 r_animcachestate.entity[idx].vertex3f = NULL;
3330 r_animcachestate.entity[idx].normal3f = NULL;
3331 r_animcachestate.entity[idx].svector3f = NULL;
3332 r_animcachestate.entity[idx].tvector3f = NULL;
3334 r_animcachestate.currentindex = 0;
3335 r_animcachestate.maxindex = 0;
3338 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3342 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3344 if (cache->maxvertices >= numvertices)
3347 // Release existing memory
3348 if (cache->vertex3f)
3349 Mem_Free(cache->vertex3f);
3351 // Pad by 1024 verts
3352 cache->maxvertices = (numvertices + 1023) & ~1023;
3353 arraySize = cache->maxvertices * 3;
3355 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3356 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3357 r_animcachestate.entity[cacheIdx].vertex3f = base;
3358 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3359 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3360 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3362 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3365 void R_AnimCache_NewFrame(void)
3369 if (r_animcache.integer && r_drawentities.integer)
3370 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3371 else if (r_animcachestate.maxindex)
3374 r_animcachestate.currentindex = 0;
3376 for (i = 0;i < r_refdef.scene.numentities;i++)
3377 r_refdef.scene.entities[i]->animcacheindex = -1;
3380 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3382 dp_model_t *model = ent->model;
3383 r_animcache_entity_t *c;
3384 // see if it's already cached this frame
3385 if (ent->animcacheindex >= 0)
3387 // add normals/tangents if needed
3388 c = r_animcachestate.entity + ent->animcacheindex;
3390 wantnormals = false;
3391 if (c->wanttangents)
3392 wanttangents = false;
3393 if (wantnormals || wanttangents)
3394 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3398 // see if this ent is worth caching
3399 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3401 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3403 // assign it a cache entry and make sure the arrays are big enough
3404 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3405 ent->animcacheindex = r_animcachestate.currentindex++;
3406 c = r_animcachestate.entity + ent->animcacheindex;
3407 c->wantnormals = wantnormals;
3408 c->wanttangents = wanttangents;
3409 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3414 void R_AnimCache_CacheVisibleEntities(void)
3417 qboolean wantnormals;
3418 qboolean wanttangents;
3420 if (!r_animcachestate.maxindex)
3423 wantnormals = !r_showsurfaces.integer;
3424 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3426 // TODO: thread this?
3428 for (i = 0;i < r_refdef.scene.numentities;i++)
3430 if (!r_refdef.viewcache.entityvisible[i])
3432 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3436 //==================================================================================
3438 static void R_View_UpdateEntityLighting (void)
3441 entity_render_t *ent;
3442 vec3_t tempdiffusenormal, avg;
3443 vec_t f, fa, fd, fdd;
3445 for (i = 0;i < r_refdef.scene.numentities;i++)
3447 ent = r_refdef.scene.entities[i];
3449 // skip unseen models
3450 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3454 if (ent->model && ent->model->brush.num_leafs)
3456 // TODO: use modellight for r_ambient settings on world?
3457 VectorSet(ent->modellight_ambient, 0, 0, 0);
3458 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3459 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3463 // fetch the lighting from the worldmodel data
3464 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));
3465 VectorClear(ent->modellight_diffuse);
3466 VectorClear(tempdiffusenormal);
3467 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3470 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3471 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3472 if(ent->flags & RENDER_EQUALIZE)
3474 // first fix up ambient lighting...
3475 if(r_equalize_entities_minambient.value > 0)
3477 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3480 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3481 if(fa < r_equalize_entities_minambient.value * fd)
3484 // fa'/fd' = minambient
3485 // fa'+0.25*fd' = fa+0.25*fd
3487 // fa' = fd' * minambient
3488 // fd'*(0.25+minambient) = fa+0.25*fd
3490 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3491 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3493 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3494 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
3495 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3496 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3501 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3503 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3504 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3507 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3508 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3509 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3515 VectorSet(ent->modellight_ambient, 1, 1, 1);
3517 // move the light direction into modelspace coordinates for lighting code
3518 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3519 if(VectorLength2(ent->modellight_lightdir) == 0)
3520 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3521 VectorNormalize(ent->modellight_lightdir);
3525 #define MAX_LINEOFSIGHTTRACES 64
3527 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3530 vec3_t boxmins, boxmaxs;
3533 dp_model_t *model = r_refdef.scene.worldmodel;
3535 if (!model || !model->brush.TraceLineOfSight)
3538 // expand the box a little
3539 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3540 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3541 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3542 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3543 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3544 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3547 VectorCopy(eye, start);
3548 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3549 if (model->brush.TraceLineOfSight(model, start, end))
3552 // try various random positions
3553 for (i = 0;i < numsamples;i++)
3555 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3556 if (model->brush.TraceLineOfSight(model, start, end))
3564 static void R_View_UpdateEntityVisible (void)
3569 entity_render_t *ent;
3571 if (!r_drawentities.integer)
3574 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3575 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3577 // worldmodel can check visibility
3578 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3579 for (i = 0;i < r_refdef.scene.numentities;i++)
3581 ent = r_refdef.scene.entities[i];
3582 if (!(ent->flags & renderimask))
3583 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)))
3584 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))
3585 r_refdef.viewcache.entityvisible[i] = true;
3587 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3589 for (i = 0;i < r_refdef.scene.numentities;i++)
3591 ent = r_refdef.scene.entities[i];
3592 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3594 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3596 continue; // temp entities do pvs only
3597 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3598 ent->last_trace_visibility = realtime;
3599 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3600 r_refdef.viewcache.entityvisible[i] = 0;
3607 // no worldmodel or it can't check visibility
3608 for (i = 0;i < r_refdef.scene.numentities;i++)
3610 ent = r_refdef.scene.entities[i];
3611 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));
3616 /// only used if skyrendermasked, and normally returns false
3617 int R_DrawBrushModelsSky (void)
3620 entity_render_t *ent;
3622 if (!r_drawentities.integer)
3626 for (i = 0;i < r_refdef.scene.numentities;i++)
3628 if (!r_refdef.viewcache.entityvisible[i])
3630 ent = r_refdef.scene.entities[i];
3631 if (!ent->model || !ent->model->DrawSky)
3633 ent->model->DrawSky(ent);
3639 static void R_DrawNoModel(entity_render_t *ent);
3640 static void R_DrawModels(void)
3643 entity_render_t *ent;
3645 if (!r_drawentities.integer)
3648 for (i = 0;i < r_refdef.scene.numentities;i++)
3650 if (!r_refdef.viewcache.entityvisible[i])
3652 ent = r_refdef.scene.entities[i];
3653 r_refdef.stats.entities++;
3654 if (ent->model && ent->model->Draw != NULL)
3655 ent->model->Draw(ent);
3661 static void R_DrawModelsDepth(void)
3664 entity_render_t *ent;
3666 if (!r_drawentities.integer)
3669 for (i = 0;i < r_refdef.scene.numentities;i++)
3671 if (!r_refdef.viewcache.entityvisible[i])
3673 ent = r_refdef.scene.entities[i];
3674 if (ent->model && ent->model->DrawDepth != NULL)
3675 ent->model->DrawDepth(ent);
3679 static void R_DrawModelsDebug(void)
3682 entity_render_t *ent;
3684 if (!r_drawentities.integer)
3687 for (i = 0;i < r_refdef.scene.numentities;i++)
3689 if (!r_refdef.viewcache.entityvisible[i])
3691 ent = r_refdef.scene.entities[i];
3692 if (ent->model && ent->model->DrawDebug != NULL)
3693 ent->model->DrawDebug(ent);
3697 static void R_DrawModelsAddWaterPlanes(void)
3700 entity_render_t *ent;
3702 if (!r_drawentities.integer)
3705 for (i = 0;i < r_refdef.scene.numentities;i++)
3707 if (!r_refdef.viewcache.entityvisible[i])
3709 ent = r_refdef.scene.entities[i];
3710 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3711 ent->model->DrawAddWaterPlanes(ent);
3715 static void R_DrawModelDecals_Entity(entity_render_t *ent);
3716 static void R_DrawModelDecals(void)
3719 entity_render_t *ent;
3721 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
3723 if (!r_drawentities.integer || r_showsurfaces.integer)
3726 for (i = 0;i < r_refdef.scene.numentities;i++)
3728 if (!r_refdef.viewcache.entityvisible[i])
3730 ent = r_refdef.scene.entities[i];
3731 r_refdef.stats.entities++;
3732 if (ent->decalsystem.numdecals)
3733 R_DrawModelDecals_Entity(ent);
3737 static void R_View_SetFrustum(void)
3740 double slopex, slopey;
3741 vec3_t forward, left, up, origin;
3743 // we can't trust r_refdef.view.forward and friends in reflected scenes
3744 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3747 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3748 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3749 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3750 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3751 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3752 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3753 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3754 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3755 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3756 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3757 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3758 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3762 zNear = r_refdef.nearclip;
3763 nudge = 1.0 - 1.0 / (1<<23);
3764 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3765 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3766 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3767 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3768 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3769 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3770 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3771 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3777 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3778 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3779 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3780 r_refdef.view.frustum[0].dist = m[15] - m[12];
3782 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3783 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3784 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3785 r_refdef.view.frustum[1].dist = m[15] + m[12];
3787 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3788 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3789 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3790 r_refdef.view.frustum[2].dist = m[15] - m[13];
3792 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3793 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3794 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3795 r_refdef.view.frustum[3].dist = m[15] + m[13];
3797 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3798 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3799 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3800 r_refdef.view.frustum[4].dist = m[15] - m[14];
3802 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3803 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3804 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3805 r_refdef.view.frustum[5].dist = m[15] + m[14];
3808 if (r_refdef.view.useperspective)
3810 slopex = 1.0 / r_refdef.view.frustum_x;
3811 slopey = 1.0 / r_refdef.view.frustum_y;
3812 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3813 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3814 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3815 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3816 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3818 // Leaving those out was a mistake, those were in the old code, and they
3819 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3820 // I couldn't reproduce it after adding those normalizations. --blub
3821 VectorNormalize(r_refdef.view.frustum[0].normal);
3822 VectorNormalize(r_refdef.view.frustum[1].normal);
3823 VectorNormalize(r_refdef.view.frustum[2].normal);
3824 VectorNormalize(r_refdef.view.frustum[3].normal);
3826 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3827 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]);
3828 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]);
3829 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]);
3830 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]);
3832 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3833 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3834 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3835 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3836 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3840 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3841 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3842 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3843 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3844 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3845 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3846 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3847 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3848 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3849 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3851 r_refdef.view.numfrustumplanes = 5;
3853 if (r_refdef.view.useclipplane)
3855 r_refdef.view.numfrustumplanes = 6;
3856 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3859 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3860 PlaneClassify(r_refdef.view.frustum + i);
3862 // LordHavoc: note to all quake engine coders, Quake had a special case
3863 // for 90 degrees which assumed a square view (wrong), so I removed it,
3864 // Quake2 has it disabled as well.
3866 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3867 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3868 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3869 //PlaneClassify(&frustum[0]);
3871 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3872 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3873 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3874 //PlaneClassify(&frustum[1]);
3876 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3877 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3878 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3879 //PlaneClassify(&frustum[2]);
3881 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3882 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3883 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3884 //PlaneClassify(&frustum[3]);
3887 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3888 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3889 //PlaneClassify(&frustum[4]);
3892 void R_View_Update(void)
3894 R_View_SetFrustum();
3895 R_View_WorldVisibility(r_refdef.view.useclipplane);
3896 R_View_UpdateEntityVisible();
3897 R_View_UpdateEntityLighting();
3900 void R_SetupView(qboolean allowwaterclippingplane)
3902 const double *customclipplane = NULL;
3904 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3906 // LordHavoc: couldn't figure out how to make this approach the
3907 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3908 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3909 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3910 dist = r_refdef.view.clipplane.dist;
3911 plane[0] = r_refdef.view.clipplane.normal[0];
3912 plane[1] = r_refdef.view.clipplane.normal[1];
3913 plane[2] = r_refdef.view.clipplane.normal[2];
3915 customclipplane = plane;
3918 if (!r_refdef.view.useperspective)
3919 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);
3920 else if (gl_stencil && r_useinfinitefarclip.integer)
3921 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);
3923 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);
3924 R_SetViewport(&r_refdef.view.viewport);
3927 void R_ResetViewRendering2D(void)
3929 r_viewport_t viewport;
3932 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3933 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);
3934 R_SetViewport(&viewport);
3935 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3936 GL_Color(1, 1, 1, 1);
3937 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3938 GL_BlendFunc(GL_ONE, GL_ZERO);
3939 GL_AlphaTest(false);
3940 GL_ScissorTest(false);
3941 GL_DepthMask(false);
3942 GL_DepthRange(0, 1);
3943 GL_DepthTest(false);
3944 R_Mesh_Matrix(&identitymatrix);
3945 R_Mesh_ResetTextureState();
3946 GL_PolygonOffset(0, 0);
3947 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3948 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3949 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3950 qglStencilMask(~0);CHECKGLERROR
3951 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3952 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3953 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3954 R_SetupGenericShader(true);
3957 void R_ResetViewRendering3D(void)
3962 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3963 GL_Color(1, 1, 1, 1);
3964 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3965 GL_BlendFunc(GL_ONE, GL_ZERO);
3966 GL_AlphaTest(false);
3967 GL_ScissorTest(true);
3969 GL_DepthRange(0, 1);
3971 R_Mesh_Matrix(&identitymatrix);
3972 R_Mesh_ResetTextureState();
3973 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3974 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3975 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3976 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3977 qglStencilMask(~0);CHECKGLERROR
3978 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3979 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3980 GL_CullFace(r_refdef.view.cullface_back);
3981 R_SetupGenericShader(true);
3984 void R_RenderScene(void);
3985 void R_RenderWaterPlanes(void);
3987 static void R_Water_StartFrame(void)
3990 int waterwidth, waterheight, texturewidth, textureheight;
3991 r_waterstate_waterplane_t *p;
3993 // set waterwidth and waterheight to the water resolution that will be
3994 // used (often less than the screen resolution for faster rendering)
3995 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3996 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3998 // calculate desired texture sizes
3999 // can't use water if the card does not support the texture size
4000 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
4001 texturewidth = textureheight = waterwidth = waterheight = 0;
4002 else if (gl_support_arb_texture_non_power_of_two)
4004 texturewidth = waterwidth;
4005 textureheight = waterheight;
4009 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4010 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4013 // allocate textures as needed
4014 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4016 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4017 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4019 if (p->texture_refraction)
4020 R_FreeTexture(p->texture_refraction);
4021 p->texture_refraction = NULL;
4022 if (p->texture_reflection)
4023 R_FreeTexture(p->texture_reflection);
4024 p->texture_reflection = NULL;
4026 memset(&r_waterstate, 0, sizeof(r_waterstate));
4027 r_waterstate.texturewidth = texturewidth;
4028 r_waterstate.textureheight = textureheight;
4031 if (r_waterstate.texturewidth)
4033 r_waterstate.enabled = true;
4035 // when doing a reduced render (HDR) we want to use a smaller area
4036 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4037 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4039 // set up variables that will be used in shader setup
4040 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4041 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4042 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4043 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4046 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4047 r_waterstate.numwaterplanes = 0;
4050 void R_Water_AddWaterPlane(msurface_t *surface)
4052 int triangleindex, planeindex;
4058 r_waterstate_waterplane_t *p;
4059 texture_t *t = R_GetCurrentTexture(surface->texture);
4060 // just use the first triangle with a valid normal for any decisions
4061 VectorClear(normal);
4062 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4064 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4065 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4066 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4067 TriangleNormal(vert[0], vert[1], vert[2], normal);
4068 if (VectorLength2(normal) >= 0.001)
4072 VectorCopy(normal, plane.normal);
4073 VectorNormalize(plane.normal);
4074 plane.dist = DotProduct(vert[0], plane.normal);
4075 PlaneClassify(&plane);
4076 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4078 // skip backfaces (except if nocullface is set)
4079 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4081 VectorNegate(plane.normal, plane.normal);
4083 PlaneClassify(&plane);
4087 // find a matching plane if there is one
4088 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4089 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4091 if (planeindex >= r_waterstate.maxwaterplanes)
4092 return; // nothing we can do, out of planes
4094 // if this triangle does not fit any known plane rendered this frame, add one
4095 if (planeindex >= r_waterstate.numwaterplanes)
4097 // store the new plane
4098 r_waterstate.numwaterplanes++;
4100 // clear materialflags and pvs
4101 p->materialflags = 0;
4102 p->pvsvalid = false;
4104 // merge this surface's materialflags into the waterplane
4105 p->materialflags |= t->currentmaterialflags;
4106 // merge this surface's PVS into the waterplane
4107 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4108 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4109 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4111 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4116 static void R_Water_ProcessPlanes(void)
4118 r_refdef_view_t originalview;
4119 r_refdef_view_t myview;
4121 r_waterstate_waterplane_t *p;
4123 originalview = r_refdef.view;
4125 // make sure enough textures are allocated
4126 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4128 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4130 if (!p->texture_refraction)
4131 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);
4132 if (!p->texture_refraction)
4136 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4138 if (!p->texture_reflection)
4139 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);
4140 if (!p->texture_reflection)
4146 r_refdef.view = originalview;
4147 r_refdef.view.showdebug = false;
4148 r_refdef.view.width = r_waterstate.waterwidth;
4149 r_refdef.view.height = r_waterstate.waterheight;
4150 r_refdef.view.useclipplane = true;
4151 myview = r_refdef.view;
4152 r_waterstate.renderingscene = true;
4153 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4155 // render the normal view scene and copy into texture
4156 // (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)
4157 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4159 r_refdef.view = myview;
4160 r_refdef.view.clipplane = p->plane;
4161 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4162 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4163 PlaneClassify(&r_refdef.view.clipplane);
4165 R_ResetViewRendering3D();
4166 R_ClearScreen(r_refdef.fogenabled);
4170 // copy view into the screen texture
4171 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4172 GL_ActiveTexture(0);
4174 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
4177 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4179 r_refdef.view = myview;
4180 // render reflected scene and copy into texture
4181 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4182 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4183 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4184 r_refdef.view.clipplane = p->plane;
4185 // reverse the cullface settings for this render
4186 r_refdef.view.cullface_front = GL_FRONT;
4187 r_refdef.view.cullface_back = GL_BACK;
4188 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4190 r_refdef.view.usecustompvs = true;
4192 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4194 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4197 R_ResetViewRendering3D();
4198 R_ClearScreen(r_refdef.fogenabled);
4202 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4203 GL_ActiveTexture(0);
4205 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
4208 r_waterstate.renderingscene = false;
4209 r_refdef.view = originalview;
4210 R_ResetViewRendering3D();
4211 R_ClearScreen(r_refdef.fogenabled);
4215 r_refdef.view = originalview;
4216 r_waterstate.renderingscene = false;
4217 Cvar_SetValueQuick(&r_water, 0);
4218 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4222 void R_Bloom_StartFrame(void)
4224 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4226 // set bloomwidth and bloomheight to the bloom resolution that will be
4227 // used (often less than the screen resolution for faster rendering)
4228 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4229 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4230 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4231 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
4232 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
4234 // calculate desired texture sizes
4235 if (gl_support_arb_texture_non_power_of_two)
4237 screentexturewidth = r_refdef.view.width;
4238 screentextureheight = r_refdef.view.height;
4239 bloomtexturewidth = r_bloomstate.bloomwidth;
4240 bloomtextureheight = r_bloomstate.bloomheight;
4244 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4245 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4246 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4247 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4250 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
4252 Cvar_SetValueQuick(&r_hdr, 0);
4253 Cvar_SetValueQuick(&r_bloom, 0);
4254 Cvar_SetValueQuick(&r_motionblur, 0);
4255 Cvar_SetValueQuick(&r_damageblur, 0);
4258 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)))
4259 screentexturewidth = screentextureheight = 0;
4260 if (!r_hdr.integer && !r_bloom.integer)
4261 bloomtexturewidth = bloomtextureheight = 0;
4263 // allocate textures as needed
4264 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4266 if (r_bloomstate.texture_screen)
4267 R_FreeTexture(r_bloomstate.texture_screen);
4268 r_bloomstate.texture_screen = NULL;
4269 r_bloomstate.screentexturewidth = screentexturewidth;
4270 r_bloomstate.screentextureheight = screentextureheight;
4271 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4272 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);
4274 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4276 if (r_bloomstate.texture_bloom)
4277 R_FreeTexture(r_bloomstate.texture_bloom);
4278 r_bloomstate.texture_bloom = NULL;
4279 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4280 r_bloomstate.bloomtextureheight = bloomtextureheight;
4281 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4282 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);
4285 // when doing a reduced render (HDR) we want to use a smaller area
4286 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4287 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4288 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4289 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4290 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4292 // set up a texcoord array for the full resolution screen image
4293 // (we have to keep this around to copy back during final render)
4294 r_bloomstate.screentexcoord2f[0] = 0;
4295 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4296 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4297 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4298 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4299 r_bloomstate.screentexcoord2f[5] = 0;
4300 r_bloomstate.screentexcoord2f[6] = 0;
4301 r_bloomstate.screentexcoord2f[7] = 0;
4303 // set up a texcoord array for the reduced resolution bloom image
4304 // (which will be additive blended over the screen image)
4305 r_bloomstate.bloomtexcoord2f[0] = 0;
4306 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4307 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4308 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4309 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4310 r_bloomstate.bloomtexcoord2f[5] = 0;
4311 r_bloomstate.bloomtexcoord2f[6] = 0;
4312 r_bloomstate.bloomtexcoord2f[7] = 0;
4314 if (r_hdr.integer || r_bloom.integer)
4316 r_bloomstate.enabled = true;
4317 r_bloomstate.hdr = r_hdr.integer != 0;
4320 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);
4323 void R_Bloom_CopyBloomTexture(float colorscale)
4325 r_refdef.stats.bloom++;
4327 // scale down screen texture to the bloom texture size
4329 R_SetViewport(&r_bloomstate.viewport);
4330 GL_BlendFunc(GL_ONE, GL_ZERO);
4331 GL_Color(colorscale, colorscale, colorscale, 1);
4332 // TODO: optimize with multitexture or GLSL
4333 R_SetupGenericShader(true);
4334 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4335 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4336 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4337 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4339 // we now have a bloom image in the framebuffer
4340 // copy it into the bloom image texture for later processing
4341 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4342 GL_ActiveTexture(0);
4344 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4345 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4348 void R_Bloom_CopyHDRTexture(void)
4350 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4351 GL_ActiveTexture(0);
4353 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
4354 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4357 void R_Bloom_MakeTexture(void)
4360 float xoffset, yoffset, r, brighten;
4362 r_refdef.stats.bloom++;
4364 R_ResetViewRendering2D();
4365 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4366 R_Mesh_ColorPointer(NULL, 0, 0);
4367 R_SetupGenericShader(true);
4369 // we have a bloom image in the framebuffer
4371 R_SetViewport(&r_bloomstate.viewport);
4373 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4376 r = bound(0, r_bloom_colorexponent.value / x, 1);
4377 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4378 GL_Color(r, r, r, 1);
4379 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4380 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4381 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4382 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4384 // copy the vertically blurred bloom view to a texture
4385 GL_ActiveTexture(0);
4387 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4388 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4391 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4392 brighten = r_bloom_brighten.value;
4394 brighten *= r_hdr_range.value;
4395 brighten = sqrt(brighten);
4397 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4398 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4399 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4401 for (dir = 0;dir < 2;dir++)
4403 // blend on at multiple vertical offsets to achieve a vertical blur
4404 // TODO: do offset blends using GLSL
4405 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4406 GL_BlendFunc(GL_ONE, GL_ZERO);
4407 for (x = -range;x <= range;x++)
4409 if (!dir){xoffset = 0;yoffset = x;}
4410 else {xoffset = x;yoffset = 0;}
4411 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4412 yoffset /= (float)r_bloomstate.bloomtextureheight;
4413 // compute a texcoord array with the specified x and y offset
4414 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4415 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4416 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4417 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4418 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4419 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4420 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4421 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4422 // this r value looks like a 'dot' particle, fading sharply to
4423 // black at the edges
4424 // (probably not realistic but looks good enough)
4425 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4426 //r = brighten/(range*2+1);
4427 r = brighten / (range * 2 + 1);
4429 r *= (1 - x*x/(float)(range*range));
4430 GL_Color(r, r, r, 1);
4431 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4432 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4433 GL_BlendFunc(GL_ONE, GL_ONE);
4436 // copy the vertically blurred bloom view to a texture
4437 GL_ActiveTexture(0);
4439 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4440 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4443 // apply subtract last
4444 // (just like it would be in a GLSL shader)
4445 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4447 GL_BlendFunc(GL_ONE, GL_ZERO);
4448 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4449 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4450 GL_Color(1, 1, 1, 1);
4451 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4452 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4454 GL_BlendFunc(GL_ONE, GL_ONE);
4455 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4456 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4457 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4458 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4459 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4460 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4461 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4463 // copy the darkened bloom view to a texture
4464 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4465 GL_ActiveTexture(0);
4467 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4468 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4472 void R_HDR_RenderBloomTexture(void)
4474 int oldwidth, oldheight;
4475 float oldcolorscale;
4477 oldcolorscale = r_refdef.view.colorscale;
4478 oldwidth = r_refdef.view.width;
4479 oldheight = r_refdef.view.height;
4480 r_refdef.view.width = r_bloomstate.bloomwidth;
4481 r_refdef.view.height = r_bloomstate.bloomheight;
4483 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4484 // TODO: add exposure compensation features
4485 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4487 r_refdef.view.showdebug = false;
4488 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4490 R_ResetViewRendering3D();
4492 R_ClearScreen(r_refdef.fogenabled);
4493 if (r_timereport_active)
4494 R_TimeReport("HDRclear");
4497 if (r_timereport_active)
4498 R_TimeReport("visibility");
4500 // only do secondary renders with HDR if r_hdr is 2 or higher
4501 r_waterstate.numwaterplanes = 0;
4502 if (r_waterstate.enabled && r_hdr.integer >= 2)
4503 R_RenderWaterPlanes();
4505 r_refdef.view.showdebug = true;
4507 r_waterstate.numwaterplanes = 0;
4509 R_ResetViewRendering2D();
4511 R_Bloom_CopyHDRTexture();
4512 R_Bloom_MakeTexture();
4514 // restore the view settings
4515 r_refdef.view.width = oldwidth;
4516 r_refdef.view.height = oldheight;
4517 r_refdef.view.colorscale = oldcolorscale;
4519 R_ResetViewRendering3D();
4521 R_ClearScreen(r_refdef.fogenabled);
4522 if (r_timereport_active)
4523 R_TimeReport("viewclear");
4526 static void R_BlendView(void)
4528 if (r_bloomstate.texture_screen)
4530 // make sure the buffer is available
4531 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4533 R_ResetViewRendering2D();
4534 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4535 R_Mesh_ColorPointer(NULL, 0, 0);
4536 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4537 GL_ActiveTexture(0);CHECKGLERROR
4539 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4541 // declare variables
4543 static float avgspeed;
4545 speed = VectorLength(cl.movement_velocity);
4547 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4548 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4550 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4551 speed = bound(0, speed, 1);
4552 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4554 // calculate values into a standard alpha
4555 cl.motionbluralpha = 1 - exp(-
4557 (r_motionblur.value * speed / 80)
4559 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4562 max(0.0001, cl.time - cl.oldtime) // fps independent
4565 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4566 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4568 if (cl.motionbluralpha > 0)
4570 R_SetupGenericShader(true);
4571 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4572 GL_Color(1, 1, 1, cl.motionbluralpha);
4573 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4574 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4575 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4576 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4580 // copy view into the screen texture
4581 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
4582 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4585 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4587 unsigned int permutation =
4588 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4589 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4590 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4591 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4592 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4594 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4596 // render simple bloom effect
4597 // copy the screen and shrink it and darken it for the bloom process
4598 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4599 // make the bloom texture
4600 R_Bloom_MakeTexture();
4603 R_ResetViewRendering2D();
4604 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4605 R_Mesh_ColorPointer(NULL, 0, 0);
4606 GL_Color(1, 1, 1, 1);
4607 GL_BlendFunc(GL_ONE, GL_ZERO);
4608 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4609 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4610 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4611 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4612 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4613 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4614 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4615 if (r_glsl_permutation->loc_TintColor >= 0)
4616 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4617 if (r_glsl_permutation->loc_ClientTime >= 0)
4618 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4619 if (r_glsl_permutation->loc_PixelSize >= 0)
4620 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4621 if (r_glsl_permutation->loc_UserVec1 >= 0)
4623 float a=0, b=0, c=0, d=0;
4624 #if _MSC_VER >= 1400
4625 #define sscanf sscanf_s
4627 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4628 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4630 if (r_glsl_permutation->loc_UserVec2 >= 0)
4632 float a=0, b=0, c=0, d=0;
4633 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4634 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4636 if (r_glsl_permutation->loc_UserVec3 >= 0)
4638 float a=0, b=0, c=0, d=0;
4639 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4640 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4642 if (r_glsl_permutation->loc_UserVec4 >= 0)
4644 float a=0, b=0, c=0, d=0;
4645 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4646 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4648 if (r_glsl_permutation->loc_Saturation >= 0)
4649 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4650 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4651 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4657 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4659 // render high dynamic range bloom effect
4660 // the bloom texture was made earlier this render, so we just need to
4661 // blend it onto the screen...
4662 R_ResetViewRendering2D();
4663 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4664 R_Mesh_ColorPointer(NULL, 0, 0);
4665 R_SetupGenericShader(true);
4666 GL_Color(1, 1, 1, 1);
4667 GL_BlendFunc(GL_ONE, GL_ONE);
4668 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4669 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4670 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4671 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4673 else if (r_bloomstate.texture_bloom)
4675 // render simple bloom effect
4676 // copy the screen and shrink it and darken it for the bloom process
4677 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4678 // make the bloom texture
4679 R_Bloom_MakeTexture();
4680 // put the original screen image back in place and blend the bloom
4682 R_ResetViewRendering2D();
4683 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4684 R_Mesh_ColorPointer(NULL, 0, 0);
4685 GL_Color(1, 1, 1, 1);
4686 GL_BlendFunc(GL_ONE, GL_ZERO);
4687 // do both in one pass if possible
4688 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4689 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4690 if (r_textureunits.integer >= 2 && gl_combine.integer)
4692 R_SetupGenericTwoTextureShader(GL_ADD);
4693 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4694 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4698 R_SetupGenericShader(true);
4699 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4700 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4701 // now blend on the bloom texture
4702 GL_BlendFunc(GL_ONE, GL_ONE);
4703 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4704 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4706 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4707 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4709 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4711 // apply a color tint to the whole view
4712 R_ResetViewRendering2D();
4713 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4714 R_Mesh_ColorPointer(NULL, 0, 0);
4715 R_SetupGenericShader(false);
4716 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4717 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4718 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4722 matrix4x4_t r_waterscrollmatrix;
4724 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4726 if (r_refdef.fog_density)
4728 r_refdef.fogcolor[0] = r_refdef.fog_red;
4729 r_refdef.fogcolor[1] = r_refdef.fog_green;
4730 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4732 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4733 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4734 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4735 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4739 VectorCopy(r_refdef.fogcolor, fogvec);
4740 // color.rgb *= ContrastBoost * SceneBrightness;
4741 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4742 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4743 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4744 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4749 void R_UpdateVariables(void)
4753 r_refdef.scene.ambient = r_ambient.value;
4755 r_refdef.farclip = r_farclip_base.value;
4756 if (r_refdef.scene.worldmodel)
4757 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
4758 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4760 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4761 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4762 r_refdef.polygonfactor = 0;
4763 r_refdef.polygonoffset = 0;
4764 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4765 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4767 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4768 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4769 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4770 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4771 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4772 if (r_showsurfaces.integer)
4774 r_refdef.scene.rtworld = false;
4775 r_refdef.scene.rtworldshadows = false;
4776 r_refdef.scene.rtdlight = false;
4777 r_refdef.scene.rtdlightshadows = false;
4778 r_refdef.lightmapintensity = 0;
4781 if (gamemode == GAME_NEHAHRA)
4783 if (gl_fogenable.integer)
4785 r_refdef.oldgl_fogenable = true;
4786 r_refdef.fog_density = gl_fogdensity.value;
4787 r_refdef.fog_red = gl_fogred.value;
4788 r_refdef.fog_green = gl_foggreen.value;
4789 r_refdef.fog_blue = gl_fogblue.value;
4790 r_refdef.fog_alpha = 1;
4791 r_refdef.fog_start = 0;
4792 r_refdef.fog_end = gl_skyclip.value;
4793 r_refdef.fog_height = 1<<30;
4794 r_refdef.fog_fadedepth = 128;
4796 else if (r_refdef.oldgl_fogenable)
4798 r_refdef.oldgl_fogenable = false;
4799 r_refdef.fog_density = 0;
4800 r_refdef.fog_red = 0;
4801 r_refdef.fog_green = 0;
4802 r_refdef.fog_blue = 0;
4803 r_refdef.fog_alpha = 0;
4804 r_refdef.fog_start = 0;
4805 r_refdef.fog_end = 0;
4806 r_refdef.fog_height = 1<<30;
4807 r_refdef.fog_fadedepth = 128;
4811 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4812 r_refdef.fog_start = max(0, r_refdef.fog_start);
4813 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4815 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4817 if (r_refdef.fog_density && r_drawfog.integer)
4819 r_refdef.fogenabled = true;
4820 // this is the point where the fog reaches 0.9986 alpha, which we
4821 // consider a good enough cutoff point for the texture
4822 // (0.9986 * 256 == 255.6)
4823 if (r_fog_exp2.integer)
4824 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4826 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4827 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4828 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4829 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4830 // fog color was already set
4831 // update the fog texture
4832 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)
4833 R_BuildFogTexture();
4836 r_refdef.fogenabled = false;
4838 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4840 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4842 // build GLSL gamma texture
4843 #define RAMPWIDTH 256
4844 unsigned short ramp[RAMPWIDTH * 3];
4845 unsigned char rampbgr[RAMPWIDTH][4];
4848 r_texture_gammaramps_serial = vid_gammatables_serial;
4850 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4851 for(i = 0; i < RAMPWIDTH; ++i)
4853 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4854 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4855 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4858 if (r_texture_gammaramps)
4860 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4864 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);
4870 // remove GLSL gamma texture
4874 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4875 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4881 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4882 if( scenetype != r_currentscenetype ) {
4883 // store the old scenetype
4884 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4885 r_currentscenetype = scenetype;
4886 // move in the new scene
4887 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4896 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4898 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4899 if( scenetype == r_currentscenetype ) {
4900 return &r_refdef.scene;
4902 return &r_scenes_store[ scenetype ];
4911 void R_RenderView(void)
4913 if (r_timereport_active)
4914 R_TimeReport("start");
4915 r_frame++; // used only by R_GetCurrentTexture
4916 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4918 R_AnimCache_NewFrame();
4920 if (r_refdef.view.isoverlay)
4922 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4923 GL_Clear( GL_DEPTH_BUFFER_BIT );
4924 R_TimeReport("depthclear");
4926 r_refdef.view.showdebug = false;
4928 r_waterstate.enabled = false;
4929 r_waterstate.numwaterplanes = 0;
4937 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4938 return; //Host_Error ("R_RenderView: NULL worldmodel");
4940 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4942 // break apart the view matrix into vectors for various purposes
4943 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4944 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4945 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4946 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4947 // make an inverted copy of the view matrix for tracking sprites
4948 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4950 R_Shadow_UpdateWorldLightSelection();
4952 R_Bloom_StartFrame();
4953 R_Water_StartFrame();
4956 if (r_timereport_active)
4957 R_TimeReport("viewsetup");
4959 R_ResetViewRendering3D();
4961 if (r_refdef.view.clear || r_refdef.fogenabled)
4963 R_ClearScreen(r_refdef.fogenabled);
4964 if (r_timereport_active)
4965 R_TimeReport("viewclear");
4967 r_refdef.view.clear = true;
4969 // this produces a bloom texture to be used in R_BlendView() later
4971 R_HDR_RenderBloomTexture();
4973 r_refdef.view.showdebug = true;
4976 if (r_timereport_active)
4977 R_TimeReport("visibility");
4979 r_waterstate.numwaterplanes = 0;
4980 if (r_waterstate.enabled)
4981 R_RenderWaterPlanes();
4984 r_waterstate.numwaterplanes = 0;
4987 if (r_timereport_active)
4988 R_TimeReport("blendview");
4990 GL_Scissor(0, 0, vid.width, vid.height);
4991 GL_ScissorTest(false);
4995 void R_RenderWaterPlanes(void)
4997 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4999 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5000 if (r_timereport_active)
5001 R_TimeReport("waterworld");
5004 // don't let sound skip if going slow
5005 if (r_refdef.scene.extraupdate)
5008 R_DrawModelsAddWaterPlanes();
5009 if (r_timereport_active)
5010 R_TimeReport("watermodels");
5012 if (r_waterstate.numwaterplanes)
5014 R_Water_ProcessPlanes();
5015 if (r_timereport_active)
5016 R_TimeReport("waterscenes");
5020 extern void R_DrawLightningBeams (void);
5021 extern void VM_CL_AddPolygonsToMeshQueue (void);
5022 extern void R_DrawPortals (void);
5023 extern cvar_t cl_locs_show;
5024 static void R_DrawLocs(void);
5025 static void R_DrawEntityBBoxes(void);
5026 extern cvar_t cl_decals_newsystem;
5027 void R_RenderScene(void)
5029 r_refdef.stats.renders++;
5031 R_Main_ResizeViewCache();
5035 // don't let sound skip if going slow
5036 if (r_refdef.scene.extraupdate)
5039 R_MeshQueue_BeginScene();
5043 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);
5045 if (cl.csqc_vidvars.drawworld)
5047 // don't let sound skip if going slow
5048 if (r_refdef.scene.extraupdate)
5051 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5053 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5054 if (r_timereport_active)
5055 R_TimeReport("worldsky");
5058 if (R_DrawBrushModelsSky() && r_timereport_active)
5059 R_TimeReport("bmodelsky");
5061 if (skyrendermasked && skyrenderlater)
5063 // we have to force off the water clipping plane while rendering sky
5070 R_AnimCache_CacheVisibleEntities();
5072 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5074 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5075 if (r_timereport_active)
5076 R_TimeReport("worlddepth");
5078 if (r_depthfirst.integer >= 2)
5080 R_DrawModelsDepth();
5081 if (r_timereport_active)
5082 R_TimeReport("modeldepth");
5085 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5087 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5088 if (r_timereport_active)
5089 R_TimeReport("world");
5092 // don't let sound skip if going slow
5093 if (r_refdef.scene.extraupdate)
5097 if (r_timereport_active)
5098 R_TimeReport("models");
5100 // don't let sound skip if going slow
5101 if (r_refdef.scene.extraupdate)
5104 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5106 R_DrawModelShadows();
5107 R_ResetViewRendering3D();
5108 // don't let sound skip if going slow
5109 if (r_refdef.scene.extraupdate)
5113 R_ShadowVolumeLighting(false);
5114 if (r_timereport_active)
5115 R_TimeReport("rtlights");
5117 // don't let sound skip if going slow
5118 if (r_refdef.scene.extraupdate)
5121 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5123 R_DrawModelShadows();
5124 R_ResetViewRendering3D();
5125 // don't let sound skip if going slow
5126 if (r_refdef.scene.extraupdate)
5130 if (cl.csqc_vidvars.drawworld)
5132 if (cl_decals_newsystem.integer)
5134 R_DrawModelDecals();
5135 if (r_timereport_active)
5136 R_TimeReport("modeldecals");
5141 if (r_timereport_active)
5142 R_TimeReport("decals");
5146 if (r_timereport_active)
5147 R_TimeReport("particles");
5150 if (r_timereport_active)
5151 R_TimeReport("explosions");
5153 R_DrawLightningBeams();
5154 if (r_timereport_active)
5155 R_TimeReport("lightning");
5158 R_SetupGenericShader(true);
5159 VM_CL_AddPolygonsToMeshQueue();
5161 if (r_refdef.view.showdebug)
5163 if (cl_locs_show.integer)
5166 if (r_timereport_active)
5167 R_TimeReport("showlocs");
5170 if (r_drawportals.integer)
5173 if (r_timereport_active)
5174 R_TimeReport("portals");
5177 if (r_showbboxes.value > 0)
5179 R_DrawEntityBBoxes();
5180 if (r_timereport_active)
5181 R_TimeReport("bboxes");
5185 R_SetupGenericShader(true);
5186 R_MeshQueue_RenderTransparent();
5187 if (r_timereport_active)
5188 R_TimeReport("drawtrans");
5190 R_SetupGenericShader(true);
5192 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))
5194 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5195 if (r_timereport_active)
5196 R_TimeReport("worlddebug");
5197 R_DrawModelsDebug();
5198 if (r_timereport_active)
5199 R_TimeReport("modeldebug");
5202 R_SetupGenericShader(true);
5204 if (cl.csqc_vidvars.drawworld)
5207 if (r_timereport_active)
5208 R_TimeReport("coronas");
5211 // don't let sound skip if going slow
5212 if (r_refdef.scene.extraupdate)
5215 R_ResetViewRendering2D();
5218 static const unsigned short bboxelements[36] =
5228 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5231 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5233 RSurf_ActiveWorldEntity();
5235 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5236 GL_DepthMask(false);
5237 GL_DepthRange(0, 1);
5238 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5239 R_Mesh_ResetTextureState();
5241 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5242 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5243 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5244 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5245 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5246 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5247 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5248 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5249 R_FillColors(color4f, 8, cr, cg, cb, ca);
5250 if (r_refdef.fogenabled)
5252 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5254 f1 = RSurf_FogVertex(v);
5256 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5257 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5258 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5261 R_Mesh_VertexPointer(vertex3f, 0, 0);
5262 R_Mesh_ColorPointer(color4f, 0, 0);
5263 R_Mesh_ResetTextureState();
5264 R_SetupGenericShader(false);
5265 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5268 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5272 prvm_edict_t *edict;
5273 prvm_prog_t *prog_save = prog;
5275 // this function draws bounding boxes of server entities
5279 GL_CullFace(GL_NONE);
5280 R_SetupGenericShader(false);
5284 for (i = 0;i < numsurfaces;i++)
5286 edict = PRVM_EDICT_NUM(surfacelist[i]);
5287 switch ((int)edict->fields.server->solid)
5289 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5290 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5291 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5292 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5293 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5294 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5296 color[3] *= r_showbboxes.value;
5297 color[3] = bound(0, color[3], 1);
5298 GL_DepthTest(!r_showdisabledepthtest.integer);
5299 GL_CullFace(r_refdef.view.cullface_front);
5300 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5306 static void R_DrawEntityBBoxes(void)
5309 prvm_edict_t *edict;
5311 prvm_prog_t *prog_save = prog;
5313 // this function draws bounding boxes of server entities
5319 for (i = 0;i < prog->num_edicts;i++)
5321 edict = PRVM_EDICT_NUM(i);
5322 if (edict->priv.server->free)
5324 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5325 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5327 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5329 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5330 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5336 static const int nomodelelement3i[24] =
5348 static const unsigned short nomodelelement3s[24] =
5360 static const float nomodelvertex3f[6*3] =
5370 static const float nomodelcolor4f[6*4] =
5372 0.0f, 0.0f, 0.5f, 1.0f,
5373 0.0f, 0.0f, 0.5f, 1.0f,
5374 0.0f, 0.5f, 0.0f, 1.0f,
5375 0.0f, 0.5f, 0.0f, 1.0f,
5376 0.5f, 0.0f, 0.0f, 1.0f,
5377 0.5f, 0.0f, 0.0f, 1.0f
5380 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5386 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);
5388 // this is only called once per entity so numsurfaces is always 1, and
5389 // surfacelist is always {0}, so this code does not handle batches
5391 if (rsurface.ent_flags & RENDER_ADDITIVE)
5393 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5394 GL_DepthMask(false);
5396 else if (rsurface.ent_color[3] < 1)
5398 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5399 GL_DepthMask(false);
5403 GL_BlendFunc(GL_ONE, GL_ZERO);
5406 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5407 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5408 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5409 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5410 R_SetupGenericShader(false);
5411 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5412 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5413 R_Mesh_ColorPointer(color4f, 0, 0);
5414 for (i = 0, c = color4f;i < 6;i++, c += 4)
5416 c[0] *= rsurface.ent_color[0];
5417 c[1] *= rsurface.ent_color[1];
5418 c[2] *= rsurface.ent_color[2];
5419 c[3] *= rsurface.ent_color[3];
5421 if (r_refdef.fogenabled)
5423 for (i = 0, c = color4f;i < 6;i++, c += 4)
5425 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5427 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5428 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5429 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5432 R_Mesh_ResetTextureState();
5433 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5436 void R_DrawNoModel(entity_render_t *ent)
5439 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5440 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5441 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5443 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5446 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5448 vec3_t right1, right2, diff, normal;
5450 VectorSubtract (org2, org1, normal);
5452 // calculate 'right' vector for start
5453 VectorSubtract (r_refdef.view.origin, org1, diff);
5454 CrossProduct (normal, diff, right1);
5455 VectorNormalize (right1);
5457 // calculate 'right' vector for end
5458 VectorSubtract (r_refdef.view.origin, org2, diff);
5459 CrossProduct (normal, diff, right2);
5460 VectorNormalize (right2);
5462 vert[ 0] = org1[0] + width * right1[0];
5463 vert[ 1] = org1[1] + width * right1[1];
5464 vert[ 2] = org1[2] + width * right1[2];
5465 vert[ 3] = org1[0] - width * right1[0];
5466 vert[ 4] = org1[1] - width * right1[1];
5467 vert[ 5] = org1[2] - width * right1[2];
5468 vert[ 6] = org2[0] - width * right2[0];
5469 vert[ 7] = org2[1] - width * right2[1];
5470 vert[ 8] = org2[2] - width * right2[2];
5471 vert[ 9] = org2[0] + width * right2[0];
5472 vert[10] = org2[1] + width * right2[1];
5473 vert[11] = org2[2] + width * right2[2];
5476 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)
5478 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5479 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5480 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5481 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5482 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5483 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5484 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5485 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5486 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5487 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5488 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5489 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5492 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5497 VectorSet(v, x, y, z);
5498 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5499 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5501 if (i == mesh->numvertices)
5503 if (mesh->numvertices < mesh->maxvertices)
5505 VectorCopy(v, vertex3f);
5506 mesh->numvertices++;
5508 return mesh->numvertices;
5514 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5518 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5519 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5520 e = mesh->element3i + mesh->numtriangles * 3;
5521 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5523 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5524 if (mesh->numtriangles < mesh->maxtriangles)
5529 mesh->numtriangles++;
5531 element[1] = element[2];
5535 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5539 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5540 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5541 e = mesh->element3i + mesh->numtriangles * 3;
5542 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5544 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5545 if (mesh->numtriangles < mesh->maxtriangles)
5550 mesh->numtriangles++;
5552 element[1] = element[2];
5556 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5557 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5559 int planenum, planenum2;
5562 mplane_t *plane, *plane2;
5564 double temppoints[2][256*3];
5565 // figure out how large a bounding box we need to properly compute this brush
5567 for (w = 0;w < numplanes;w++)
5568 maxdist = max(maxdist, fabs(planes[w].dist));
5569 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5570 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5571 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5575 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5576 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5578 if (planenum2 == planenum)
5580 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);
5583 if (tempnumpoints < 3)
5585 // generate elements forming a triangle fan for this polygon
5586 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5590 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)
5592 texturelayer_t *layer;
5593 layer = t->currentlayers + t->currentnumlayers++;
5595 layer->depthmask = depthmask;
5596 layer->blendfunc1 = blendfunc1;
5597 layer->blendfunc2 = blendfunc2;
5598 layer->texture = texture;
5599 layer->texmatrix = *matrix;
5600 layer->color[0] = r * r_refdef.view.colorscale;
5601 layer->color[1] = g * r_refdef.view.colorscale;
5602 layer->color[2] = b * r_refdef.view.colorscale;
5603 layer->color[3] = a;
5606 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5609 index = parms[2] + r_refdef.scene.time * parms[3];
5610 index -= floor(index);
5614 case Q3WAVEFUNC_NONE:
5615 case Q3WAVEFUNC_NOISE:
5616 case Q3WAVEFUNC_COUNT:
5619 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5620 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5621 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5622 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5623 case Q3WAVEFUNC_TRIANGLE:
5625 f = index - floor(index);
5636 return (float)(parms[0] + parms[1] * f);
5639 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5644 matrix4x4_t matrix, temp;
5645 switch(tcmod->tcmod)
5649 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5650 matrix = r_waterscrollmatrix;
5652 matrix = identitymatrix;
5654 case Q3TCMOD_ENTITYTRANSLATE:
5655 // this is used in Q3 to allow the gamecode to control texcoord
5656 // scrolling on the entity, which is not supported in darkplaces yet.
5657 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5659 case Q3TCMOD_ROTATE:
5660 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5661 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5662 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5665 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5667 case Q3TCMOD_SCROLL:
5668 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5670 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5671 w = (int) tcmod->parms[0];
5672 h = (int) tcmod->parms[1];
5673 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5675 idx = (int) floor(f * w * h);
5676 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5678 case Q3TCMOD_STRETCH:
5679 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5680 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5682 case Q3TCMOD_TRANSFORM:
5683 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5684 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5685 VectorSet(tcmat + 6, 0 , 0 , 1);
5686 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5687 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5689 case Q3TCMOD_TURBULENT:
5690 // this is handled in the RSurf_PrepareVertices function
5691 matrix = identitymatrix;
5695 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5698 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5700 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5701 char name[MAX_QPATH];
5702 skinframe_t *skinframe;
5703 unsigned char pixels[296*194];
5704 strlcpy(cache->name, skinname, sizeof(cache->name));
5705 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5706 if (developer_loading.integer)
5707 Con_Printf("loading %s\n", name);
5708 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5709 if (!skinframe || !skinframe->base)
5712 fs_offset_t filesize;
5714 f = FS_LoadFile(name, tempmempool, true, &filesize);
5717 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5718 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5722 cache->skinframe = skinframe;
5725 texture_t *R_GetCurrentTexture(texture_t *t)
5728 const entity_render_t *ent = rsurface.entity;
5729 dp_model_t *model = ent->model;
5730 q3shaderinfo_layer_tcmod_t *tcmod;
5732 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5733 return t->currentframe;
5734 t->update_lastrenderframe = r_frame;
5735 t->update_lastrenderentity = (void *)ent;
5737 // switch to an alternate material if this is a q1bsp animated material
5739 texture_t *texture = t;
5740 int s = rsurface.ent_skinnum;
5741 if ((unsigned int)s >= (unsigned int)model->numskins)
5743 if (model->skinscenes)
5745 if (model->skinscenes[s].framecount > 1)
5746 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5748 s = model->skinscenes[s].firstframe;
5751 t = t + s * model->num_surfaces;
5754 // use an alternate animation if the entity's frame is not 0,
5755 // and only if the texture has an alternate animation
5756 if (rsurface.ent_alttextures && t->anim_total[1])
5757 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5759 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5761 texture->currentframe = t;
5764 // update currentskinframe to be a qw skin or animation frame
5765 if (rsurface.ent_qwskin >= 0)
5767 i = rsurface.ent_qwskin;
5768 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5770 r_qwskincache_size = cl.maxclients;
5772 Mem_Free(r_qwskincache);
5773 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5775 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5776 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5777 t->currentskinframe = r_qwskincache[i].skinframe;
5778 if (t->currentskinframe == NULL)
5779 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5781 else if (t->numskinframes >= 2)
5782 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5783 if (t->backgroundnumskinframes >= 2)
5784 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5786 t->currentmaterialflags = t->basematerialflags;
5787 t->currentalpha = rsurface.ent_color[3];
5788 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5789 t->currentalpha *= r_wateralpha.value;
5790 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5791 t->currentalpha *= t->r_water_wateralpha;
5792 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5793 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5794 if (!(rsurface.ent_flags & RENDER_LIGHT))
5795 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5796 else if (rsurface.modeltexcoordlightmap2f == NULL)
5798 // pick a model lighting mode
5799 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5800 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5802 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5804 if (rsurface.ent_flags & RENDER_ADDITIVE)
5805 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5806 else if (t->currentalpha < 1)
5807 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5808 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5809 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5810 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5811 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5812 if (t->backgroundnumskinframes)
5813 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5814 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5816 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5817 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5820 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5822 // there is no tcmod
5823 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5825 t->currenttexmatrix = r_waterscrollmatrix;
5826 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5828 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
5830 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5831 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5834 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5835 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5836 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5837 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5839 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5840 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5841 t->glosstexture = r_texture_black;
5842 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5843 t->backgroundglosstexture = r_texture_black;
5844 t->specularpower = r_shadow_glossexponent.value;
5845 // TODO: store reference values for these in the texture?
5846 t->specularscale = 0;
5847 if (r_shadow_gloss.integer > 0)
5849 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5851 if (r_shadow_glossintensity.value > 0)
5853 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5854 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5855 t->specularscale = r_shadow_glossintensity.value;
5858 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5860 t->glosstexture = r_texture_white;
5861 t->backgroundglosstexture = r_texture_white;
5862 t->specularscale = r_shadow_gloss2intensity.value;
5863 t->specularpower = r_shadow_gloss2exponent.value;
5866 t->specularscale *= t->specularscalemod;
5867 t->specularpower *= t->specularpowermod;
5869 // lightmaps mode looks bad with dlights using actual texturing, so turn
5870 // off the colormap and glossmap, but leave the normalmap on as it still
5871 // accurately represents the shading involved
5872 if (gl_lightmaps.integer)
5874 t->basetexture = r_texture_grey128;
5875 t->backgroundbasetexture = NULL;
5876 t->specularscale = 0;
5877 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5880 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5881 VectorClear(t->dlightcolor);
5882 t->currentnumlayers = 0;
5883 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5886 int blendfunc1, blendfunc2;
5888 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5890 blendfunc1 = GL_SRC_ALPHA;
5891 blendfunc2 = GL_ONE;
5893 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5895 blendfunc1 = GL_SRC_ALPHA;
5896 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5898 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5900 blendfunc1 = t->customblendfunc[0];
5901 blendfunc2 = t->customblendfunc[1];
5905 blendfunc1 = GL_ONE;
5906 blendfunc2 = GL_ZERO;
5908 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5909 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5910 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5911 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5913 // fullbright is not affected by r_refdef.lightmapintensity
5914 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]);
5915 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5916 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]);
5917 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5918 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]);
5922 vec3_t ambientcolor;
5924 // set the color tint used for lights affecting this surface
5925 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5927 // q3bsp has no lightmap updates, so the lightstylevalue that
5928 // would normally be baked into the lightmap must be
5929 // applied to the color
5930 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5931 if (model->type == mod_brushq3)
5932 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5933 colorscale *= r_refdef.lightmapintensity;
5934 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5935 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5936 // basic lit geometry
5937 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]);
5938 // add pants/shirt if needed
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_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]);
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_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]);
5943 // now add ambient passes if needed
5944 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5946 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]);
5947 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5948 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]);
5949 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5950 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]);
5953 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5954 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]);
5955 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5957 // if this is opaque use alpha blend which will darken the earlier
5960 // if this is an alpha blended material, all the earlier passes
5961 // were darkened by fog already, so we only need to add the fog
5962 // color ontop through the fog mask texture
5964 // if this is an additive blended material, all the earlier passes
5965 // were darkened by fog already, and we should not add fog color
5966 // (because the background was not darkened, there is no fog color
5967 // that was lost behind it).
5968 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]);
5972 return t->currentframe;
5975 rsurfacestate_t rsurface;
5977 void R_Mesh_ResizeArrays(int newvertices)
5980 if (rsurface.array_size >= newvertices)
5982 if (rsurface.array_modelvertex3f)
5983 Mem_Free(rsurface.array_modelvertex3f);
5984 rsurface.array_size = (newvertices + 1023) & ~1023;
5985 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5986 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5987 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5988 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5989 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5990 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5991 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5992 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5993 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5994 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5995 rsurface.array_color4f = base + rsurface.array_size * 27;
5996 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5999 void RSurf_ActiveWorldEntity(void)
6001 dp_model_t *model = r_refdef.scene.worldmodel;
6002 //if (rsurface.entity == r_refdef.scene.worldentity)
6004 rsurface.entity = r_refdef.scene.worldentity;
6005 rsurface.ent_skinnum = 0;
6006 rsurface.ent_qwskin = -1;
6007 rsurface.ent_shadertime = 0;
6008 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
6009 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6010 if (rsurface.array_size < model->surfmesh.num_vertices)
6011 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6012 rsurface.matrix = identitymatrix;
6013 rsurface.inversematrix = identitymatrix;
6014 rsurface.matrixscale = 1;
6015 rsurface.inversematrixscale = 1;
6016 R_Mesh_Matrix(&identitymatrix);
6017 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6018 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6019 rsurface.fograngerecip = r_refdef.fograngerecip;
6020 rsurface.fogheightfade = r_refdef.fogheightfade;
6021 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6022 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6023 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6024 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6025 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6026 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6027 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6028 VectorSet(rsurface.glowmod, 1, 1, 1);
6029 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6030 rsurface.frameblend[0].lerp = 1;
6031 rsurface.ent_alttextures = false;
6032 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6033 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6034 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6035 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6036 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6037 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6038 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6039 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6040 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6041 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6042 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6043 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6044 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6045 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6046 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6047 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6048 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6049 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6050 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6051 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6052 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6053 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6054 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6055 rsurface.modelelement3i = model->surfmesh.data_element3i;
6056 rsurface.modelelement3s = model->surfmesh.data_element3s;
6057 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6058 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6059 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6060 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6061 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6062 rsurface.modelsurfaces = model->data_surfaces;
6063 rsurface.generatedvertex = false;
6064 rsurface.vertex3f = rsurface.modelvertex3f;
6065 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6066 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6067 rsurface.svector3f = rsurface.modelsvector3f;
6068 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6069 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6070 rsurface.tvector3f = rsurface.modeltvector3f;
6071 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6072 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6073 rsurface.normal3f = rsurface.modelnormal3f;
6074 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6075 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6076 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6079 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6081 dp_model_t *model = ent->model;
6082 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6084 rsurface.entity = (entity_render_t *)ent;
6085 rsurface.ent_skinnum = ent->skinnum;
6086 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;
6087 rsurface.ent_shadertime = ent->shadertime;
6088 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6089 rsurface.ent_flags = ent->flags;
6090 if (rsurface.array_size < model->surfmesh.num_vertices)
6091 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6092 rsurface.matrix = ent->matrix;
6093 rsurface.inversematrix = ent->inversematrix;
6094 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6095 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6096 R_Mesh_Matrix(&rsurface.matrix);
6097 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6098 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6099 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6100 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6101 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6102 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6103 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6104 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6105 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6106 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6107 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6108 VectorCopy(ent->glowmod, rsurface.glowmod);
6109 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6110 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6111 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6112 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6113 if (ent->model->brush.submodel)
6115 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6116 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6118 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6120 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6122 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6123 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6124 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6125 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6127 else if (wanttangents)
6129 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6130 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6131 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6132 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6133 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6135 else if (wantnormals)
6137 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6138 rsurface.modelsvector3f = NULL;
6139 rsurface.modeltvector3f = NULL;
6140 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6141 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6145 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6146 rsurface.modelsvector3f = NULL;
6147 rsurface.modeltvector3f = NULL;
6148 rsurface.modelnormal3f = NULL;
6149 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6151 rsurface.modelvertex3f_bufferobject = 0;
6152 rsurface.modelvertex3f_bufferoffset = 0;
6153 rsurface.modelsvector3f_bufferobject = 0;
6154 rsurface.modelsvector3f_bufferoffset = 0;
6155 rsurface.modeltvector3f_bufferobject = 0;
6156 rsurface.modeltvector3f_bufferoffset = 0;
6157 rsurface.modelnormal3f_bufferobject = 0;
6158 rsurface.modelnormal3f_bufferoffset = 0;
6159 rsurface.generatedvertex = true;
6163 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6164 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6165 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6166 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6167 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6168 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6169 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6170 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6171 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6172 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6173 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6174 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6175 rsurface.generatedvertex = false;
6177 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6178 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6179 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6180 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6181 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6182 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6183 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6184 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6185 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6186 rsurface.modelelement3i = model->surfmesh.data_element3i;
6187 rsurface.modelelement3s = model->surfmesh.data_element3s;
6188 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6189 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6190 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6191 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6192 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6193 rsurface.modelsurfaces = model->data_surfaces;
6194 rsurface.vertex3f = rsurface.modelvertex3f;
6195 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6196 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6197 rsurface.svector3f = rsurface.modelsvector3f;
6198 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6199 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6200 rsurface.tvector3f = rsurface.modeltvector3f;
6201 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6202 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6203 rsurface.normal3f = rsurface.modelnormal3f;
6204 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6205 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6206 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6209 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)
6211 rsurface.entity = r_refdef.scene.worldentity;
6212 rsurface.ent_skinnum = 0;
6213 rsurface.ent_qwskin = -1;
6214 rsurface.ent_shadertime = shadertime;
6215 Vector4Set(rsurface.ent_color, r, g, b, a);
6216 rsurface.ent_flags = entflags;
6217 rsurface.modelnum_vertices = numvertices;
6218 rsurface.modelnum_triangles = numtriangles;
6219 if (rsurface.array_size < rsurface.modelnum_vertices)
6220 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6221 rsurface.matrix = *matrix;
6222 rsurface.inversematrix = *inversematrix;
6223 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6224 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6225 R_Mesh_Matrix(&rsurface.matrix);
6226 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6227 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6228 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6229 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6230 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6231 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6232 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6233 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6234 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6235 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6236 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6237 VectorSet(rsurface.glowmod, 1, 1, 1);
6238 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6239 rsurface.frameblend[0].lerp = 1;
6240 rsurface.ent_alttextures = false;
6241 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6242 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6245 rsurface.modelvertex3f = vertex3f;
6246 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6247 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6248 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6250 else if (wantnormals)
6252 rsurface.modelvertex3f = vertex3f;
6253 rsurface.modelsvector3f = NULL;
6254 rsurface.modeltvector3f = NULL;
6255 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6259 rsurface.modelvertex3f = vertex3f;
6260 rsurface.modelsvector3f = NULL;
6261 rsurface.modeltvector3f = NULL;
6262 rsurface.modelnormal3f = NULL;
6264 rsurface.modelvertex3f_bufferobject = 0;
6265 rsurface.modelvertex3f_bufferoffset = 0;
6266 rsurface.modelsvector3f_bufferobject = 0;
6267 rsurface.modelsvector3f_bufferoffset = 0;
6268 rsurface.modeltvector3f_bufferobject = 0;
6269 rsurface.modeltvector3f_bufferoffset = 0;
6270 rsurface.modelnormal3f_bufferobject = 0;
6271 rsurface.modelnormal3f_bufferoffset = 0;
6272 rsurface.generatedvertex = true;
6273 rsurface.modellightmapcolor4f = color4f;
6274 rsurface.modellightmapcolor4f_bufferobject = 0;
6275 rsurface.modellightmapcolor4f_bufferoffset = 0;
6276 rsurface.modeltexcoordtexture2f = texcoord2f;
6277 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6278 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6279 rsurface.modeltexcoordlightmap2f = NULL;
6280 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6281 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6282 rsurface.modelelement3i = element3i;
6283 rsurface.modelelement3s = element3s;
6284 rsurface.modelelement3i_bufferobject = 0;
6285 rsurface.modelelement3s_bufferobject = 0;
6286 rsurface.modellightmapoffsets = NULL;
6287 rsurface.modelsurfaces = NULL;
6288 rsurface.vertex3f = rsurface.modelvertex3f;
6289 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6290 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6291 rsurface.svector3f = rsurface.modelsvector3f;
6292 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6293 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6294 rsurface.tvector3f = rsurface.modeltvector3f;
6295 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6296 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6297 rsurface.normal3f = rsurface.modelnormal3f;
6298 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6299 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6300 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6302 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6304 if ((wantnormals || wanttangents) && !normal3f)
6305 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6306 if (wanttangents && !svector3f)
6307 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);
6311 float RSurf_FogPoint(const float *v)
6313 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6314 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6315 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6316 float FogHeightFade = r_refdef.fogheightfade;
6318 unsigned int fogmasktableindex;
6319 if (r_refdef.fogplaneviewabove)
6320 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6322 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6323 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6324 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6327 float RSurf_FogVertex(const float *v)
6329 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6330 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6331 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6332 float FogHeightFade = rsurface.fogheightfade;
6334 unsigned int fogmasktableindex;
6335 if (r_refdef.fogplaneviewabove)
6336 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6338 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6339 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6340 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6343 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6344 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6347 int texturesurfaceindex;
6352 const float *v1, *in_tc;
6354 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6356 q3shaderinfo_deform_t *deform;
6357 // 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
6358 if (rsurface.generatedvertex)
6360 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6361 generatenormals = true;
6362 for (i = 0;i < Q3MAXDEFORMS;i++)
6364 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6366 generatetangents = true;
6367 generatenormals = true;
6369 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6370 generatenormals = true;
6372 if (generatenormals && !rsurface.modelnormal3f)
6374 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6375 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6376 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6377 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6379 if (generatetangents && !rsurface.modelsvector3f)
6381 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6382 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6383 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6384 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6385 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6386 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6387 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);
6390 rsurface.vertex3f = rsurface.modelvertex3f;
6391 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6392 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6393 rsurface.svector3f = rsurface.modelsvector3f;
6394 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6395 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6396 rsurface.tvector3f = rsurface.modeltvector3f;
6397 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6398 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6399 rsurface.normal3f = rsurface.modelnormal3f;
6400 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6401 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6402 // if vertices are deformed (sprite flares and things in maps, possibly
6403 // water waves, bulges and other deformations), generate them into
6404 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6405 // (may be static model data or generated data for an animated model, or
6406 // the previous deform pass)
6407 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6409 switch (deform->deform)
6412 case Q3DEFORM_PROJECTIONSHADOW:
6413 case Q3DEFORM_TEXT0:
6414 case Q3DEFORM_TEXT1:
6415 case Q3DEFORM_TEXT2:
6416 case Q3DEFORM_TEXT3:
6417 case Q3DEFORM_TEXT4:
6418 case Q3DEFORM_TEXT5:
6419 case Q3DEFORM_TEXT6:
6420 case Q3DEFORM_TEXT7:
6423 case Q3DEFORM_AUTOSPRITE:
6424 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6425 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6426 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6427 VectorNormalize(newforward);
6428 VectorNormalize(newright);
6429 VectorNormalize(newup);
6430 // make deformed versions of only the model vertices used by the specified surfaces
6431 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6433 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6434 // a single autosprite surface can contain multiple sprites...
6435 for (j = 0;j < surface->num_vertices - 3;j += 4)
6437 VectorClear(center);
6438 for (i = 0;i < 4;i++)
6439 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6440 VectorScale(center, 0.25f, center);
6441 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6442 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6443 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6444 for (i = 0;i < 4;i++)
6446 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6447 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6450 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);
6451 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);
6453 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6454 rsurface.vertex3f_bufferobject = 0;
6455 rsurface.vertex3f_bufferoffset = 0;
6456 rsurface.svector3f = rsurface.array_deformedsvector3f;
6457 rsurface.svector3f_bufferobject = 0;
6458 rsurface.svector3f_bufferoffset = 0;
6459 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6460 rsurface.tvector3f_bufferobject = 0;
6461 rsurface.tvector3f_bufferoffset = 0;
6462 rsurface.normal3f = rsurface.array_deformednormal3f;
6463 rsurface.normal3f_bufferobject = 0;
6464 rsurface.normal3f_bufferoffset = 0;
6466 case Q3DEFORM_AUTOSPRITE2:
6467 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6468 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6469 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6470 VectorNormalize(newforward);
6471 VectorNormalize(newright);
6472 VectorNormalize(newup);
6473 // make deformed versions of only the model vertices used by the specified surfaces
6474 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6476 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6477 const float *v1, *v2;
6487 memset(shortest, 0, sizeof(shortest));
6488 // a single autosprite surface can contain multiple sprites...
6489 for (j = 0;j < surface->num_vertices - 3;j += 4)
6491 VectorClear(center);
6492 for (i = 0;i < 4;i++)
6493 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6494 VectorScale(center, 0.25f, center);
6495 // find the two shortest edges, then use them to define the
6496 // axis vectors for rotating around the central axis
6497 for (i = 0;i < 6;i++)
6499 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6500 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6502 Debug_PolygonBegin(NULL, 0);
6503 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6504 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);
6505 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6508 l = VectorDistance2(v1, v2);
6509 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6511 l += (1.0f / 1024.0f);
6512 if (shortest[0].length2 > l || i == 0)
6514 shortest[1] = shortest[0];
6515 shortest[0].length2 = l;
6516 shortest[0].v1 = v1;
6517 shortest[0].v2 = v2;
6519 else if (shortest[1].length2 > l || i == 1)
6521 shortest[1].length2 = l;
6522 shortest[1].v1 = v1;
6523 shortest[1].v2 = v2;
6526 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6527 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6529 Debug_PolygonBegin(NULL, 0);
6530 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6531 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);
6532 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6535 // this calculates the right vector from the shortest edge
6536 // and the up vector from the edge midpoints
6537 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6538 VectorNormalize(right);
6539 VectorSubtract(end, start, up);
6540 VectorNormalize(up);
6541 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6542 VectorSubtract(rsurface.localvieworigin, center, forward);
6543 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6544 VectorNegate(forward, forward);
6545 VectorReflect(forward, 0, up, forward);
6546 VectorNormalize(forward);
6547 CrossProduct(up, forward, newright);
6548 VectorNormalize(newright);
6550 Debug_PolygonBegin(NULL, 0);
6551 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);
6552 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6553 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6557 Debug_PolygonBegin(NULL, 0);
6558 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6559 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6560 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6563 // rotate the quad around the up axis vector, this is made
6564 // especially easy by the fact we know the quad is flat,
6565 // so we only have to subtract the center position and
6566 // measure distance along the right vector, and then
6567 // multiply that by the newright vector and add back the
6569 // we also need to subtract the old position to undo the
6570 // displacement from the center, which we do with a
6571 // DotProduct, the subtraction/addition of center is also
6572 // optimized into DotProducts here
6573 l = DotProduct(right, center);
6574 for (i = 0;i < 4;i++)
6576 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6577 f = DotProduct(right, v1) - l;
6578 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6581 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);
6582 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);
6584 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6585 rsurface.vertex3f_bufferobject = 0;
6586 rsurface.vertex3f_bufferoffset = 0;
6587 rsurface.svector3f = rsurface.array_deformedsvector3f;
6588 rsurface.svector3f_bufferobject = 0;
6589 rsurface.svector3f_bufferoffset = 0;
6590 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6591 rsurface.tvector3f_bufferobject = 0;
6592 rsurface.tvector3f_bufferoffset = 0;
6593 rsurface.normal3f = rsurface.array_deformednormal3f;
6594 rsurface.normal3f_bufferobject = 0;
6595 rsurface.normal3f_bufferoffset = 0;
6597 case Q3DEFORM_NORMAL:
6598 // deform the normals to make reflections wavey
6599 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6601 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6602 for (j = 0;j < surface->num_vertices;j++)
6605 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6606 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6607 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6608 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6609 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6610 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6611 VectorNormalize(normal);
6613 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);
6615 rsurface.svector3f = rsurface.array_deformedsvector3f;
6616 rsurface.svector3f_bufferobject = 0;
6617 rsurface.svector3f_bufferoffset = 0;
6618 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6619 rsurface.tvector3f_bufferobject = 0;
6620 rsurface.tvector3f_bufferoffset = 0;
6621 rsurface.normal3f = rsurface.array_deformednormal3f;
6622 rsurface.normal3f_bufferobject = 0;
6623 rsurface.normal3f_bufferoffset = 0;
6626 // deform vertex array to make wavey water and flags and such
6627 waveparms[0] = deform->waveparms[0];
6628 waveparms[1] = deform->waveparms[1];
6629 waveparms[2] = deform->waveparms[2];
6630 waveparms[3] = deform->waveparms[3];
6631 // this is how a divisor of vertex influence on deformation
6632 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6633 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6634 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6636 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6637 for (j = 0;j < surface->num_vertices;j++)
6639 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6640 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6641 // if the wavefunc depends on time, evaluate it per-vertex
6644 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6645 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6647 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6650 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6651 rsurface.vertex3f_bufferobject = 0;
6652 rsurface.vertex3f_bufferoffset = 0;
6654 case Q3DEFORM_BULGE:
6655 // deform vertex array to make the surface have moving bulges
6656 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6658 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6659 for (j = 0;j < surface->num_vertices;j++)
6661 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6662 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6665 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6666 rsurface.vertex3f_bufferobject = 0;
6667 rsurface.vertex3f_bufferoffset = 0;
6670 // deform vertex array
6671 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6672 VectorScale(deform->parms, scale, waveparms);
6673 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6675 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6676 for (j = 0;j < surface->num_vertices;j++)
6677 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6679 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6680 rsurface.vertex3f_bufferobject = 0;
6681 rsurface.vertex3f_bufferoffset = 0;
6685 // generate texcoords based on the chosen texcoord source
6686 switch(rsurface.texture->tcgen.tcgen)
6689 case Q3TCGEN_TEXTURE:
6690 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6691 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6692 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6694 case Q3TCGEN_LIGHTMAP:
6695 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6696 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6697 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6699 case Q3TCGEN_VECTOR:
6700 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6702 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6703 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)
6705 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6706 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6709 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6710 rsurface.texcoordtexture2f_bufferobject = 0;
6711 rsurface.texcoordtexture2f_bufferoffset = 0;
6713 case Q3TCGEN_ENVIRONMENT:
6714 // make environment reflections using a spheremap
6715 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6717 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6718 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6719 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6720 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6721 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6723 // identical to Q3A's method, but executed in worldspace so
6724 // carried models can be shiny too
6726 float viewer[3], d, reflected[3], worldreflected[3];
6728 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6729 // VectorNormalize(viewer);
6731 d = DotProduct(normal, viewer);
6733 reflected[0] = normal[0]*2*d - viewer[0];
6734 reflected[1] = normal[1]*2*d - viewer[1];
6735 reflected[2] = normal[2]*2*d - viewer[2];
6736 // note: this is proportinal to viewer, so we can normalize later
6738 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6739 VectorNormalize(worldreflected);
6741 // note: this sphere map only uses world x and z!
6742 // so positive and negative y will LOOK THE SAME.
6743 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6744 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6747 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6748 rsurface.texcoordtexture2f_bufferobject = 0;
6749 rsurface.texcoordtexture2f_bufferoffset = 0;
6752 // the only tcmod that needs software vertex processing is turbulent, so
6753 // check for it here and apply the changes if needed
6754 // and we only support that as the first one
6755 // (handling a mixture of turbulent and other tcmods would be problematic
6756 // without punting it entirely to a software path)
6757 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6759 amplitude = rsurface.texture->tcmods[0].parms[1];
6760 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6761 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6763 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6764 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)
6766 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6767 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6770 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6771 rsurface.texcoordtexture2f_bufferobject = 0;
6772 rsurface.texcoordtexture2f_bufferoffset = 0;
6774 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6775 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6776 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6777 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6780 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6783 const msurface_t *surface = texturesurfacelist[0];
6784 const msurface_t *surface2;
6789 // TODO: lock all array ranges before render, rather than on each surface
6790 if (texturenumsurfaces == 1)
6792 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6793 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);
6795 else if (r_batchmode.integer == 2)
6797 #define MAXBATCHTRIANGLES 4096
6798 int batchtriangles = 0;
6799 int batchelements[MAXBATCHTRIANGLES*3];
6800 for (i = 0;i < texturenumsurfaces;i = j)
6802 surface = texturesurfacelist[i];
6804 if (surface->num_triangles > MAXBATCHTRIANGLES)
6806 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);
6809 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6810 batchtriangles = surface->num_triangles;
6811 firstvertex = surface->num_firstvertex;
6812 endvertex = surface->num_firstvertex + surface->num_vertices;
6813 for (;j < texturenumsurfaces;j++)
6815 surface2 = texturesurfacelist[j];
6816 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6818 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6819 batchtriangles += surface2->num_triangles;
6820 firstvertex = min(firstvertex, surface2->num_firstvertex);
6821 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6823 surface2 = texturesurfacelist[j-1];
6824 numvertices = endvertex - firstvertex;
6825 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6828 else if (r_batchmode.integer == 1)
6830 for (i = 0;i < texturenumsurfaces;i = j)
6832 surface = texturesurfacelist[i];
6833 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6834 if (texturesurfacelist[j] != surface2)
6836 surface2 = texturesurfacelist[j-1];
6837 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6838 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6839 GL_LockArrays(surface->num_firstvertex, numvertices);
6840 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6845 for (i = 0;i < texturenumsurfaces;i++)
6847 surface = texturesurfacelist[i];
6848 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6849 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);
6854 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6856 int i, planeindex, vertexindex;
6860 r_waterstate_waterplane_t *p, *bestp;
6861 const msurface_t *surface;
6862 if (r_waterstate.renderingscene)
6864 for (i = 0;i < texturenumsurfaces;i++)
6866 surface = texturesurfacelist[i];
6867 if (lightmaptexunit >= 0)
6868 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6869 if (deluxemaptexunit >= 0)
6870 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6871 // pick the closest matching water plane
6874 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6877 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6879 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6880 d += fabs(PlaneDiff(vert, &p->plane));
6882 if (bestd > d || !bestp)
6890 if (refractiontexunit >= 0)
6891 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6892 if (reflectiontexunit >= 0)
6893 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6897 if (refractiontexunit >= 0)
6898 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6899 if (reflectiontexunit >= 0)
6900 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6902 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6903 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);
6907 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6911 const msurface_t *surface = texturesurfacelist[0];
6912 const msurface_t *surface2;
6917 // TODO: lock all array ranges before render, rather than on each surface
6918 if (texturenumsurfaces == 1)
6920 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6921 if (deluxemaptexunit >= 0)
6922 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6923 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6924 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6926 else if (r_batchmode.integer == 2)
6928 #define MAXBATCHTRIANGLES 4096
6929 int batchtriangles = 0;
6930 int batchelements[MAXBATCHTRIANGLES*3];
6931 for (i = 0;i < texturenumsurfaces;i = j)
6933 surface = texturesurfacelist[i];
6934 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6935 if (deluxemaptexunit >= 0)
6936 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6938 if (surface->num_triangles > MAXBATCHTRIANGLES)
6940 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);
6943 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6944 batchtriangles = surface->num_triangles;
6945 firstvertex = surface->num_firstvertex;
6946 endvertex = surface->num_firstvertex + surface->num_vertices;
6947 for (;j < texturenumsurfaces;j++)
6949 surface2 = texturesurfacelist[j];
6950 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6952 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6953 batchtriangles += surface2->num_triangles;
6954 firstvertex = min(firstvertex, surface2->num_firstvertex);
6955 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6957 surface2 = texturesurfacelist[j-1];
6958 numvertices = endvertex - firstvertex;
6959 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6962 else if (r_batchmode.integer == 1)
6965 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6966 for (i = 0;i < texturenumsurfaces;i = j)
6968 surface = texturesurfacelist[i];
6969 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6970 if (texturesurfacelist[j] != surface2)
6972 Con_Printf(" %i", j - i);
6975 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6977 for (i = 0;i < texturenumsurfaces;i = j)
6979 surface = texturesurfacelist[i];
6980 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6981 if (deluxemaptexunit >= 0)
6982 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6983 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6984 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6987 Con_Printf(" %i", j - i);
6989 surface2 = texturesurfacelist[j-1];
6990 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6991 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6992 GL_LockArrays(surface->num_firstvertex, numvertices);
6993 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7001 for (i = 0;i < texturenumsurfaces;i++)
7003 surface = texturesurfacelist[i];
7004 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7005 if (deluxemaptexunit >= 0)
7006 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7007 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7008 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);
7013 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7016 int texturesurfaceindex;
7017 if (r_showsurfaces.integer == 2)
7019 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7021 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7022 for (j = 0;j < surface->num_triangles;j++)
7024 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7025 GL_Color(f, f, f, 1);
7026 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7032 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7034 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7035 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7036 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);
7037 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7038 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);
7043 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7045 int texturesurfaceindex;
7049 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7051 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7052 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)
7060 rsurface.lightmapcolor4f = rsurface.array_color4f;
7061 rsurface.lightmapcolor4f_bufferobject = 0;
7062 rsurface.lightmapcolor4f_bufferoffset = 0;
7065 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7067 int texturesurfaceindex;
7073 if (rsurface.lightmapcolor4f)
7075 // generate color arrays for the surfaces in this list
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), 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)
7081 f = RSurf_FogVertex(v);
7091 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7093 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7094 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)
7096 f = RSurf_FogVertex(v);
7104 rsurface.lightmapcolor4f = rsurface.array_color4f;
7105 rsurface.lightmapcolor4f_bufferobject = 0;
7106 rsurface.lightmapcolor4f_bufferoffset = 0;
7109 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7111 int texturesurfaceindex;
7117 if (!rsurface.lightmapcolor4f)
7119 // generate color arrays for the surfaces in this list
7120 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7122 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7123 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)
7125 f = RSurf_FogVertex(v);
7126 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7127 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7128 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7132 rsurface.lightmapcolor4f = rsurface.array_color4f;
7133 rsurface.lightmapcolor4f_bufferobject = 0;
7134 rsurface.lightmapcolor4f_bufferoffset = 0;
7137 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7139 int texturesurfaceindex;
7143 if (!rsurface.lightmapcolor4f)
7145 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7147 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7148 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)
7156 rsurface.lightmapcolor4f = rsurface.array_color4f;
7157 rsurface.lightmapcolor4f_bufferobject = 0;
7158 rsurface.lightmapcolor4f_bufferoffset = 0;
7161 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7163 int texturesurfaceindex;
7167 if (!rsurface.lightmapcolor4f)
7169 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7171 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7172 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)
7174 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7175 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7176 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7180 rsurface.lightmapcolor4f = rsurface.array_color4f;
7181 rsurface.lightmapcolor4f_bufferobject = 0;
7182 rsurface.lightmapcolor4f_bufferoffset = 0;
7185 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7188 rsurface.lightmapcolor4f = NULL;
7189 rsurface.lightmapcolor4f_bufferobject = 0;
7190 rsurface.lightmapcolor4f_bufferoffset = 0;
7191 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7192 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7193 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7194 GL_Color(r, g, b, a);
7195 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7198 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7200 // TODO: optimize applyfog && applycolor case
7201 // just apply fog if necessary, and tint the fog color array if necessary
7202 rsurface.lightmapcolor4f = NULL;
7203 rsurface.lightmapcolor4f_bufferobject = 0;
7204 rsurface.lightmapcolor4f_bufferoffset = 0;
7205 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7206 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7207 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7208 GL_Color(r, g, b, a);
7209 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7212 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7214 int texturesurfaceindex;
7218 if (texturesurfacelist[0]->lightmapinfo)
7220 // generate color arrays for the surfaces in this list
7221 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7223 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7224 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7226 if (surface->lightmapinfo->samples)
7228 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7229 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7230 VectorScale(lm, scale, c);
7231 if (surface->lightmapinfo->styles[1] != 255)
7233 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7235 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7236 VectorMA(c, scale, lm, c);
7237 if (surface->lightmapinfo->styles[2] != 255)
7240 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7241 VectorMA(c, scale, lm, c);
7242 if (surface->lightmapinfo->styles[3] != 255)
7245 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7246 VectorMA(c, scale, lm, c);
7256 rsurface.lightmapcolor4f = rsurface.array_color4f;
7257 rsurface.lightmapcolor4f_bufferobject = 0;
7258 rsurface.lightmapcolor4f_bufferoffset = 0;
7262 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7263 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7264 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7266 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7267 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7268 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7269 GL_Color(r, g, b, a);
7270 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7273 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7275 int texturesurfaceindex;
7282 vec3_t ambientcolor;
7283 vec3_t diffusecolor;
7287 VectorCopy(rsurface.modellight_lightdir, lightdir);
7288 f = 0.5f * r_refdef.lightmapintensity;
7289 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7290 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7291 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7292 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7293 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7294 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7296 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7298 // generate color arrays for the surfaces in this list
7299 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7301 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7302 int numverts = surface->num_vertices;
7303 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7304 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7305 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7306 // q3-style directional shading
7307 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7309 if ((f = DotProduct(n, lightdir)) > 0)
7310 VectorMA(ambientcolor, f, diffusecolor, c);
7312 VectorCopy(ambientcolor, c);
7320 rsurface.lightmapcolor4f = rsurface.array_color4f;
7321 rsurface.lightmapcolor4f_bufferobject = 0;
7322 rsurface.lightmapcolor4f_bufferoffset = 0;
7323 *applycolor = false;
7327 *r = ambientcolor[0];
7328 *g = ambientcolor[1];
7329 *b = ambientcolor[2];
7330 rsurface.lightmapcolor4f = NULL;
7331 rsurface.lightmapcolor4f_bufferobject = 0;
7332 rsurface.lightmapcolor4f_bufferoffset = 0;
7336 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7338 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7339 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7340 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7341 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7342 GL_Color(r, g, b, a);
7343 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7346 void RSurf_SetupDepthAndCulling(void)
7348 // submodels are biased to avoid z-fighting with world surfaces that they
7349 // may be exactly overlapping (avoids z-fighting artifacts on certain
7350 // doors and things in Quake maps)
7351 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7352 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7353 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7354 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7357 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7359 // transparent sky would be ridiculous
7360 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7362 R_SetupGenericShader(false);
7363 skyrenderlater = true;
7364 RSurf_SetupDepthAndCulling();
7366 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7367 // skymasking on them, and Quake3 never did sky masking (unlike
7368 // software Quake and software Quake2), so disable the sky masking
7369 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7370 // and skymasking also looks very bad when noclipping outside the
7371 // level, so don't use it then either.
7372 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7374 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7375 R_Mesh_ColorPointer(NULL, 0, 0);
7376 R_Mesh_ResetTextureState();
7377 if (skyrendermasked)
7379 R_SetupDepthOrShadowShader();
7380 // depth-only (masking)
7381 GL_ColorMask(0,0,0,0);
7382 // just to make sure that braindead drivers don't draw
7383 // anything despite that colormask...
7384 GL_BlendFunc(GL_ZERO, GL_ONE);
7388 R_SetupGenericShader(false);
7390 GL_BlendFunc(GL_ONE, GL_ZERO);
7392 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7393 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7394 if (skyrendermasked)
7395 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7397 R_Mesh_ResetTextureState();
7398 GL_Color(1, 1, 1, 1);
7401 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7403 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7406 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7407 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7408 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7409 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7410 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7411 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7412 if (rsurface.texture->backgroundcurrentskinframe)
7414 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7415 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7416 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7417 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7419 if(rsurface.texture->colormapping)
7421 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7422 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7424 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7425 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7426 R_Mesh_ColorPointer(NULL, 0, 0);
7428 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7430 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7432 // render background
7433 GL_BlendFunc(GL_ONE, GL_ZERO);
7435 GL_AlphaTest(false);
7437 GL_Color(1, 1, 1, 1);
7438 R_Mesh_ColorPointer(NULL, 0, 0);
7440 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7441 if (r_glsl_permutation)
7443 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7444 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7445 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7446 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7447 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7448 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7449 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);
7451 GL_LockArrays(0, 0);
7453 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7454 GL_DepthMask(false);
7455 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7456 R_Mesh_ColorPointer(NULL, 0, 0);
7458 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7459 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7460 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7463 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7464 if (!r_glsl_permutation)
7467 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7468 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7469 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7470 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7471 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7472 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7474 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7476 GL_BlendFunc(GL_ONE, GL_ZERO);
7478 GL_AlphaTest(false);
7482 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7483 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7484 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7487 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7489 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7490 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);
7492 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7496 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7497 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);
7499 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7501 GL_LockArrays(0, 0);
7504 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7506 // OpenGL 1.3 path - anything not completely ancient
7507 int texturesurfaceindex;
7508 qboolean applycolor;
7512 const texturelayer_t *layer;
7513 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7515 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7518 int layertexrgbscale;
7519 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7521 if (layerindex == 0)
7525 GL_AlphaTest(false);
7526 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7529 GL_DepthMask(layer->depthmask && writedepth);
7530 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7531 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7533 layertexrgbscale = 4;
7534 VectorScale(layer->color, 0.25f, layercolor);
7536 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7538 layertexrgbscale = 2;
7539 VectorScale(layer->color, 0.5f, layercolor);
7543 layertexrgbscale = 1;
7544 VectorScale(layer->color, 1.0f, layercolor);
7546 layercolor[3] = layer->color[3];
7547 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7548 R_Mesh_ColorPointer(NULL, 0, 0);
7549 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7550 switch (layer->type)
7552 case TEXTURELAYERTYPE_LITTEXTURE:
7553 memset(&m, 0, sizeof(m));
7554 m.tex[0] = R_GetTexture(r_texture_white);
7555 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7556 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7557 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7558 m.tex[1] = R_GetTexture(layer->texture);
7559 m.texmatrix[1] = layer->texmatrix;
7560 m.texrgbscale[1] = layertexrgbscale;
7561 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7562 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7563 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7564 R_Mesh_TextureState(&m);
7565 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7566 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7567 else if (rsurface.uselightmaptexture)
7568 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7570 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7572 case TEXTURELAYERTYPE_TEXTURE:
7573 memset(&m, 0, sizeof(m));
7574 m.tex[0] = R_GetTexture(layer->texture);
7575 m.texmatrix[0] = layer->texmatrix;
7576 m.texrgbscale[0] = layertexrgbscale;
7577 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7578 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7579 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7580 R_Mesh_TextureState(&m);
7581 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7583 case TEXTURELAYERTYPE_FOG:
7584 memset(&m, 0, sizeof(m));
7585 m.texrgbscale[0] = layertexrgbscale;
7588 m.tex[0] = R_GetTexture(layer->texture);
7589 m.texmatrix[0] = layer->texmatrix;
7590 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7591 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7592 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7594 R_Mesh_TextureState(&m);
7595 // generate a color array for the fog pass
7596 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7597 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7603 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7604 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)
7606 f = 1 - RSurf_FogVertex(v);
7607 c[0] = layercolor[0];
7608 c[1] = layercolor[1];
7609 c[2] = layercolor[2];
7610 c[3] = f * layercolor[3];
7613 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7616 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7618 GL_LockArrays(0, 0);
7621 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7623 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7624 GL_AlphaTest(false);
7628 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7630 // OpenGL 1.1 - crusty old voodoo path
7631 int texturesurfaceindex;
7635 const texturelayer_t *layer;
7636 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7638 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7640 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7642 if (layerindex == 0)
7646 GL_AlphaTest(false);
7647 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7650 GL_DepthMask(layer->depthmask && writedepth);
7651 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7652 R_Mesh_ColorPointer(NULL, 0, 0);
7653 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7654 switch (layer->type)
7656 case TEXTURELAYERTYPE_LITTEXTURE:
7657 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7659 // two-pass lit texture with 2x rgbscale
7660 // first the lightmap pass
7661 memset(&m, 0, sizeof(m));
7662 m.tex[0] = R_GetTexture(r_texture_white);
7663 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7664 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7665 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7666 R_Mesh_TextureState(&m);
7667 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7668 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7669 else if (rsurface.uselightmaptexture)
7670 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7672 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7673 GL_LockArrays(0, 0);
7674 // then apply the texture to it
7675 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7676 memset(&m, 0, sizeof(m));
7677 m.tex[0] = R_GetTexture(layer->texture);
7678 m.texmatrix[0] = layer->texmatrix;
7679 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7680 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7681 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7682 R_Mesh_TextureState(&m);
7683 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);
7687 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7688 memset(&m, 0, sizeof(m));
7689 m.tex[0] = R_GetTexture(layer->texture);
7690 m.texmatrix[0] = layer->texmatrix;
7691 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7692 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7693 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7694 R_Mesh_TextureState(&m);
7695 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7696 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);
7698 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);
7701 case TEXTURELAYERTYPE_TEXTURE:
7702 // singletexture unlit texture with transparency support
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], 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);
7712 case TEXTURELAYERTYPE_FOG:
7713 // singletexture fogging
7714 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7717 memset(&m, 0, sizeof(m));
7718 m.tex[0] = R_GetTexture(layer->texture);
7719 m.texmatrix[0] = layer->texmatrix;
7720 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7721 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7722 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7723 R_Mesh_TextureState(&m);
7726 R_Mesh_ResetTextureState();
7727 // generate a color array for the fog pass
7728 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7734 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7735 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)
7737 f = 1 - RSurf_FogVertex(v);
7738 c[0] = layer->color[0];
7739 c[1] = layer->color[1];
7740 c[2] = layer->color[2];
7741 c[3] = f * layer->color[3];
7744 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7747 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7749 GL_LockArrays(0, 0);
7752 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7754 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7755 GL_AlphaTest(false);
7759 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7763 GL_AlphaTest(false);
7764 R_Mesh_ColorPointer(NULL, 0, 0);
7765 R_Mesh_ResetTextureState();
7766 R_SetupGenericShader(false);
7768 if(rsurface.texture && rsurface.texture->currentskinframe)
7770 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7771 c[3] *= rsurface.texture->currentalpha;
7781 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7783 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7784 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7785 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7788 // brighten it up (as texture value 127 means "unlit")
7789 c[0] *= 2 * r_refdef.view.colorscale;
7790 c[1] *= 2 * r_refdef.view.colorscale;
7791 c[2] *= 2 * r_refdef.view.colorscale;
7793 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7794 c[3] *= r_wateralpha.value;
7796 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7798 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7799 GL_DepthMask(false);
7801 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7803 GL_BlendFunc(GL_ONE, GL_ONE);
7804 GL_DepthMask(false);
7806 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7808 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7809 GL_DepthMask(false);
7811 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7813 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7814 GL_DepthMask(false);
7818 GL_BlendFunc(GL_ONE, GL_ZERO);
7819 GL_DepthMask(writedepth);
7822 rsurface.lightmapcolor4f = NULL;
7824 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7826 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7828 rsurface.lightmapcolor4f = NULL;
7829 rsurface.lightmapcolor4f_bufferobject = 0;
7830 rsurface.lightmapcolor4f_bufferoffset = 0;
7832 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7834 qboolean applycolor = true;
7837 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7839 r_refdef.lightmapintensity = 1;
7840 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7841 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7845 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7847 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7848 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7849 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7852 if(!rsurface.lightmapcolor4f)
7853 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7855 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7856 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7857 if(r_refdef.fogenabled)
7858 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7860 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7861 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7864 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7867 RSurf_SetupDepthAndCulling();
7868 if (r_showsurfaces.integer == 3)
7869 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7870 else if (r_glsl.integer && gl_support_fragment_shader)
7871 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7872 else if (gl_combine.integer && r_textureunits.integer >= 2)
7873 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7875 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7879 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7882 RSurf_SetupDepthAndCulling();
7883 if (r_showsurfaces.integer == 3)
7884 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7885 else if (r_glsl.integer && gl_support_fragment_shader)
7886 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7887 else if (gl_combine.integer && r_textureunits.integer >= 2)
7888 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7890 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7894 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7897 int texturenumsurfaces, endsurface;
7899 const msurface_t *surface;
7900 const msurface_t *texturesurfacelist[1024];
7902 // if the model is static it doesn't matter what value we give for
7903 // wantnormals and wanttangents, so this logic uses only rules applicable
7904 // to a model, knowing that they are meaningless otherwise
7905 if (ent == r_refdef.scene.worldentity)
7906 RSurf_ActiveWorldEntity();
7907 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7908 RSurf_ActiveModelEntity(ent, false, false);
7910 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7912 for (i = 0;i < numsurfaces;i = j)
7915 surface = rsurface.modelsurfaces + surfacelist[i];
7916 texture = surface->texture;
7917 rsurface.texture = R_GetCurrentTexture(texture);
7918 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7919 // scan ahead until we find a different texture
7920 endsurface = min(i + 1024, numsurfaces);
7921 texturenumsurfaces = 0;
7922 texturesurfacelist[texturenumsurfaces++] = surface;
7923 for (;j < endsurface;j++)
7925 surface = rsurface.modelsurfaces + surfacelist[j];
7926 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7928 texturesurfacelist[texturenumsurfaces++] = surface;
7930 // render the range of surfaces
7931 if (ent == r_refdef.scene.worldentity)
7932 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7934 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7936 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7937 GL_AlphaTest(false);
7940 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7942 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7946 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7948 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7950 RSurf_SetupDepthAndCulling();
7951 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7952 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7954 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7956 RSurf_SetupDepthAndCulling();
7957 GL_AlphaTest(false);
7958 R_Mesh_ColorPointer(NULL, 0, 0);
7959 R_Mesh_ResetTextureState();
7960 R_SetupGenericShader(false);
7961 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7963 GL_BlendFunc(GL_ONE, GL_ZERO);
7964 GL_Color(0, 0, 0, 1);
7965 GL_DepthTest(writedepth);
7966 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7968 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7970 RSurf_SetupDepthAndCulling();
7971 GL_AlphaTest(false);
7972 R_Mesh_ColorPointer(NULL, 0, 0);
7973 R_Mesh_ResetTextureState();
7974 R_SetupGenericShader(false);
7975 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7977 GL_BlendFunc(GL_ONE, GL_ZERO);
7979 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7981 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7982 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7983 else if (!rsurface.texture->currentnumlayers)
7985 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7987 // transparent surfaces get pushed off into the transparent queue
7988 int surfacelistindex;
7989 const msurface_t *surface;
7990 vec3_t tempcenter, center;
7991 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7993 surface = texturesurfacelist[surfacelistindex];
7994 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7995 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7996 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7997 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7998 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8003 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8004 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8009 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8013 // break the surface list down into batches by texture and use of lightmapping
8014 for (i = 0;i < numsurfaces;i = j)
8017 // texture is the base texture pointer, rsurface.texture is the
8018 // current frame/skin the texture is directing us to use (for example
8019 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8020 // use skin 1 instead)
8021 texture = surfacelist[i]->texture;
8022 rsurface.texture = R_GetCurrentTexture(texture);
8023 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8024 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8026 // if this texture is not the kind we want, skip ahead to the next one
8027 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8031 // simply scan ahead until we find a different texture or lightmap state
8032 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8034 // render the range of surfaces
8035 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
8039 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
8044 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8046 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8048 RSurf_SetupDepthAndCulling();
8049 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8050 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8052 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8054 RSurf_SetupDepthAndCulling();
8055 GL_AlphaTest(false);
8056 R_Mesh_ColorPointer(NULL, 0, 0);
8057 R_Mesh_ResetTextureState();
8058 R_SetupGenericShader(false);
8059 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8061 GL_BlendFunc(GL_ONE, GL_ZERO);
8062 GL_Color(0, 0, 0, 1);
8063 GL_DepthTest(writedepth);
8064 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8066 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8068 RSurf_SetupDepthAndCulling();
8069 GL_AlphaTest(false);
8070 R_Mesh_ColorPointer(NULL, 0, 0);
8071 R_Mesh_ResetTextureState();
8072 R_SetupGenericShader(false);
8073 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8075 GL_BlendFunc(GL_ONE, GL_ZERO);
8077 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8079 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8080 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8081 else if (!rsurface.texture->currentnumlayers)
8083 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8085 // transparent surfaces get pushed off into the transparent queue
8086 int surfacelistindex;
8087 const msurface_t *surface;
8088 vec3_t tempcenter, center;
8089 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8091 surface = texturesurfacelist[surfacelistindex];
8092 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8093 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8094 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8095 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8096 if (queueentity->transparent_offset) // transparent offset
8098 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8099 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8100 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8102 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8107 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8108 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8113 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8117 // break the surface list down into batches by texture and use of lightmapping
8118 for (i = 0;i < numsurfaces;i = j)
8121 // texture is the base texture pointer, rsurface.texture is the
8122 // current frame/skin the texture is directing us to use (for example
8123 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8124 // use skin 1 instead)
8125 texture = surfacelist[i]->texture;
8126 rsurface.texture = R_GetCurrentTexture(texture);
8127 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8128 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8130 // if this texture is not the kind we want, skip ahead to the next one
8131 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8135 // simply scan ahead until we find a different texture or lightmap state
8136 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8138 // render the range of surfaces
8139 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8143 float locboxvertex3f[6*4*3] =
8145 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8146 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8147 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8148 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8149 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8150 1,0,0, 0,0,0, 0,1,0, 1,1,0
8153 unsigned short locboxelements[6*2*3] =
8163 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8166 cl_locnode_t *loc = (cl_locnode_t *)ent;
8168 float vertex3f[6*4*3];
8170 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8171 GL_DepthMask(false);
8172 GL_DepthRange(0, 1);
8173 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8175 GL_CullFace(GL_NONE);
8176 R_Mesh_Matrix(&identitymatrix);
8178 R_Mesh_VertexPointer(vertex3f, 0, 0);
8179 R_Mesh_ColorPointer(NULL, 0, 0);
8180 R_Mesh_ResetTextureState();
8181 R_SetupGenericShader(false);
8184 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8185 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8186 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8187 surfacelist[0] < 0 ? 0.5f : 0.125f);
8189 if (VectorCompare(loc->mins, loc->maxs))
8191 VectorSet(size, 2, 2, 2);
8192 VectorMA(loc->mins, -0.5f, size, mins);
8196 VectorCopy(loc->mins, mins);
8197 VectorSubtract(loc->maxs, loc->mins, size);
8200 for (i = 0;i < 6*4*3;)
8201 for (j = 0;j < 3;j++, i++)
8202 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8204 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8207 void R_DrawLocs(void)
8210 cl_locnode_t *loc, *nearestloc;
8212 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8213 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8215 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8216 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8220 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8222 if (decalsystem->decals)
8223 Mem_Free(decalsystem->decals);
8224 memset(decalsystem, 0, sizeof(*decalsystem));
8227 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)
8238 // expand or initialize the system
8239 if (decalsystem->maxdecals <= decalsystem->numdecals)
8241 decalsystem_t old = *decalsystem;
8242 qboolean useshortelements;
8243 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8244 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8245 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)));
8246 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8247 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8248 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8249 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8250 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8251 if (decalsystem->numdecals)
8253 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8254 memcpy(decalsystem->vertex3f, old.vertex3f, decalsystem->numdecals * sizeof(float[3][3]));
8255 memcpy(decalsystem->texcoord2f, old.texcoord2f, decalsystem->numdecals * sizeof(float[3][2]));
8256 memcpy(decalsystem->color4f, old.color4f, decalsystem->numdecals * sizeof(float[3][4]));
8258 Mem_Free(old.decals);
8259 for (i = 0;i < decalsystem->maxdecals*3;i++)
8260 decalsystem->element3i[i] = i;
8261 if (useshortelements)
8262 for (i = 0;i < decalsystem->maxdecals*3;i++)
8263 decalsystem->element3s[i] = i;
8266 // grab a decal and search for another free slot for the next one
8267 maxdecals = decalsystem->maxdecals;
8268 decals = decalsystem->decals;
8269 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8270 v3f = decalsystem->vertex3f + 9*i;
8271 tc2f = decalsystem->texcoord2f + 6*i;
8272 c4f = decalsystem->color4f + 12*i;
8273 for (i = decalsystem->freedecal;i < maxdecals && decals[i].colors[0][3];i++)
8275 decalsystem->freedecal = i;
8276 if (decalsystem->numdecals <= i)
8277 decalsystem->numdecals = i + 1;
8279 // initialize the decal
8281 decal->triangleindex = triangleindex;
8282 decal->colors[0][0] = (unsigned char)(c0[0]*255.0f);
8283 decal->colors[0][1] = (unsigned char)(c0[1]*255.0f);
8284 decal->colors[0][2] = (unsigned char)(c0[2]*255.0f);
8285 decal->colors[0][3] = 255;
8286 decal->colors[1][0] = (unsigned char)(c1[0]*255.0f);
8287 decal->colors[1][1] = (unsigned char)(c1[1]*255.0f);
8288 decal->colors[1][2] = (unsigned char)(c1[2]*255.0f);
8289 decal->colors[1][3] = 255;
8290 decal->colors[2][0] = (unsigned char)(c2[0]*255.0f);
8291 decal->colors[2][1] = (unsigned char)(c2[1]*255.0f);
8292 decal->colors[2][2] = (unsigned char)(c2[2]*255.0f);
8293 decal->colors[2][3] = 255;
8310 c4f[ 0] = decal->colors[0][0] * ca;
8311 c4f[ 1] = decal->colors[0][1] * ca;
8312 c4f[ 2] = decal->colors[0][2] * ca;
8314 c4f[ 4] = decal->colors[1][0] * ca;
8315 c4f[ 5] = decal->colors[1][1] * ca;
8316 c4f[ 6] = decal->colors[1][2] * ca;
8318 c4f[ 8] = decal->colors[2][0] * ca;
8319 c4f[ 9] = decal->colors[2][1] * ca;
8320 c4f[10] = decal->colors[2][2] * ca;
8324 extern cvar_t cl_decals_bias;
8325 extern cvar_t cl_decals_models;
8326 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)
8328 matrix4x4_t projection;
8329 decalsystem_t *decalsystem;
8332 const float *vertex3f;
8333 const msurface_t *surface;
8334 const msurface_t *surfaces;
8335 const int *surfacelist;
8336 const texture_t *texture;
8340 int surfacelistindex;
8346 float localorigin[3];
8347 float localnormal[3];
8358 float points[2][9][3];
8362 decalsystem = &ent->decalsystem;
8364 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8366 R_DecalSystem_Reset(&ent->decalsystem);
8370 if (!model->brush.data_nodes && !cl_decals_models.integer)
8372 if (decalsystem->model)
8373 R_DecalSystem_Reset(decalsystem);
8377 if (decalsystem->model != model)
8378 R_DecalSystem_Reset(decalsystem);
8379 decalsystem->model = model;
8381 RSurf_ActiveModelEntity(ent, false, false);
8383 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8384 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8385 VectorNormalize(localnormal);
8386 localsize = worldsize*rsurface.inversematrixscale;
8387 ilocalsize = 1.0f / localsize;
8388 localmins[0] = localorigin[0] - localsize;
8389 localmins[1] = localorigin[1] - localsize;
8390 localmins[2] = localorigin[2] - localsize;
8391 localmaxs[0] = localorigin[0] + localsize;
8392 localmaxs[1] = localorigin[1] + localsize;
8393 localmaxs[2] = localorigin[2] + localsize;
8395 //VectorCopy(localnormal, planes[4]);
8396 //VectorVectors(planes[4], planes[2], planes[0]);
8397 AnglesFromVectors(angles, localnormal, NULL, false);
8398 AngleVectors(angles, planes[0], planes[2], planes[4]);
8399 VectorNegate(planes[0], planes[1]);
8400 VectorNegate(planes[2], planes[3]);
8401 VectorNegate(planes[4], planes[5]);
8402 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8403 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8404 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8405 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8406 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8407 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8412 matrix4x4_t forwardprojection;
8413 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8414 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8419 float projectionvector[4][3];
8420 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8421 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8422 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8423 projectionvector[0][0] = planes[0][0] * ilocalsize;
8424 projectionvector[0][1] = planes[1][0] * ilocalsize;
8425 projectionvector[0][2] = planes[2][0] * ilocalsize;
8426 projectionvector[1][0] = planes[0][1] * ilocalsize;
8427 projectionvector[1][1] = planes[1][1] * ilocalsize;
8428 projectionvector[1][2] = planes[2][1] * ilocalsize;
8429 projectionvector[2][0] = planes[0][2] * ilocalsize;
8430 projectionvector[2][1] = planes[1][2] * ilocalsize;
8431 projectionvector[2][2] = planes[2][2] * ilocalsize;
8432 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8433 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8434 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8435 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8439 dynamic = model->surfmesh.isanimated;
8440 vertex3f = rsurface.modelvertex3f;
8441 numsurfacelist = model->nummodelsurfaces;
8442 surfacelist = model->sortedmodelsurfaces;
8443 surfaces = model->data_surfaces;
8444 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8446 surface = surfaces + surfacelist[surfacelistindex];
8447 // skip transparent surfaces
8448 texture = surface->texture;
8449 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8451 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8453 if (texture->currentalpha < 1)
8455 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8457 numvertices = surface->num_vertices;
8458 numtriangles = surface->num_triangles;
8459 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8461 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8463 index = 3*e[cornerindex];
8464 VectorCopy(vertex3f + index, v[cornerindex]);
8467 //TriangleNormal(v[0], v[1], v[2], normal);
8468 //if (DotProduct(normal, localnormal) < 0.0f)
8470 // clip by each of the box planes formed from the projection matrix
8471 // if anything survives, we emit the decal
8472 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]);
8475 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]);
8478 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]);
8481 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]);
8484 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]);
8487 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]);
8490 // some part of the triangle survived, so we have to accept it...
8493 // dynamic always uses the original triangle
8495 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8497 index = 3*e[cornerindex];
8498 VectorCopy(vertex3f + index, v[cornerindex]);
8501 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8503 // convert vertex positions to texcoords
8504 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8505 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8506 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8507 // calculate distance fade from the projection origin
8508 f = a * (1.0f-fabs(temp[0]));
8510 c[cornerindex][0] = r * f;
8511 c[cornerindex][1] = g * f;
8512 c[cornerindex][2] = b * f;
8513 c[cornerindex][3] = 1.0f;
8514 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8517 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex);
8519 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8520 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);
8525 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)
8527 int renderentityindex;
8530 entity_render_t *ent;
8532 worldmins[0] = worldorigin[0] - worldsize;
8533 worldmins[1] = worldorigin[1] - worldsize;
8534 worldmins[2] = worldorigin[2] - worldsize;
8535 worldmaxs[0] = worldorigin[0] + worldsize;
8536 worldmaxs[1] = worldorigin[1] + worldsize;
8537 worldmaxs[2] = worldorigin[2] + worldsize;
8539 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8541 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8543 ent = r_refdef.scene.entities[renderentityindex];
8544 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8547 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8551 extern skinframe_t *decalskinframe;
8552 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8555 decalsystem_t *decalsystem = &ent->decalsystem;
8566 if (!decalsystem->numdecals)
8569 if (r_showsurfaces.integer)
8572 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8574 R_DecalSystem_Reset(decalsystem);
8578 // if the model is static it doesn't matter what value we give for
8579 // wantnormals and wanttangents, so this logic uses only rules applicable
8580 // to a model, knowing that they are meaningless otherwise
8581 if (ent == r_refdef.scene.worldentity)
8582 RSurf_ActiveWorldEntity();
8584 RSurf_ActiveModelEntity(ent, false, false);
8586 if (decalsystem->lastupdatetime)
8587 frametime = cl.time - decalsystem->lastupdatetime;
8590 decalsystem->lastupdatetime = cl.time;
8591 decal = decalsystem->decals;
8592 numdecals = decalsystem->numdecals;
8594 fadedelay = cl_decals_time.value;
8595 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
8597 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8599 if (!decal->colors[0][3])
8602 decal->lived += frametime;
8603 if (decal->lived >= fadedelay)
8605 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
8608 // kill the decal by zeroing vertex data
8609 memset(decalsystem->vertex3f + 9*i, 0, sizeof(float[3][3]));
8610 memset(decalsystem->texcoord2f + 6*i, 0, sizeof(float[3][2]));
8611 memset(decalsystem->color4f + 12*i, 0, sizeof(float[3][4]));
8612 memset(decal, 0, sizeof(*decal));
8613 if (decalsystem->freedecal > i)
8614 decalsystem->freedecal = i;
8618 // update color values for fading decals
8619 alpha *= (1.0f/255.0f);
8620 c4f = decalsystem->color4f + 12*i;
8621 c4f[ 0] = decal->colors[0][0] * alpha;
8622 c4f[ 1] = decal->colors[0][1] * alpha;
8623 c4f[ 2] = decal->colors[0][2] * alpha;
8625 c4f[ 4] = decal->colors[1][0] * alpha;
8626 c4f[ 5] = decal->colors[1][1] * alpha;
8627 c4f[ 6] = decal->colors[1][2] * alpha;
8629 c4f[ 8] = decal->colors[2][0] * alpha;
8630 c4f[ 9] = decal->colors[2][1] * alpha;
8631 c4f[10] = decal->colors[2][2] * alpha;
8635 // update vertex positions for animated models
8636 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8638 e = rsurface.modelelement3i + 3*decal->triangleindex;
8639 v3f = decalsystem->vertex3f + 9*i;
8640 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8641 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8642 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8646 // reduce numdecals if possible
8647 while (numdecals > 0 && !decalsystem->decals[numdecals - 1].colors[0][3])
8649 decalsystem->numdecals = numdecals;
8653 r_refdef.stats.decals += numdecals;
8654 // now render the decals all at once
8655 // (this assumes they all use one particle font texture!)
8656 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numdecals, decalsystem->element3i, decalsystem->element3s, false, false);
8657 R_Mesh_ResetTextureState();
8658 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8659 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8660 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8661 R_SetupGenericShader(true);
8662 GL_DepthMask(false);
8663 GL_DepthRange(0, 1);
8664 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
8666 GL_CullFace(GL_NONE);
8667 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8668 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8669 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8670 GL_LockArrays(0, numdecals * 3);
8671 R_Mesh_Draw(0, numdecals * 3, 0, numdecals, decalsystem->element3i, decalsystem->element3s, 0, 0);
8672 GL_LockArrays(0, 0);
8677 // if there are no decals left, reset decalsystem
8678 R_DecalSystem_Reset(decalsystem);
8682 void R_DrawDebugModel(void)
8684 entity_render_t *ent = rsurface.entity;
8685 int i, j, k, l, flagsmask;
8686 const int *elements;
8688 const msurface_t *surface;
8689 dp_model_t *model = ent->model;
8692 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8694 R_Mesh_ColorPointer(NULL, 0, 0);
8695 R_Mesh_ResetTextureState();
8696 R_SetupGenericShader(false);
8697 GL_DepthRange(0, 1);
8698 GL_DepthTest(!r_showdisabledepthtest.integer);
8699 GL_DepthMask(false);
8700 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8702 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8704 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8705 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8707 if (brush->colbrushf && brush->colbrushf->numtriangles)
8709 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8710 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);
8711 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8714 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8716 if (surface->num_collisiontriangles)
8718 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8719 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);
8720 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8725 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8727 if (r_showtris.integer || r_shownormals.integer)
8729 if (r_showdisabledepthtest.integer)
8731 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8732 GL_DepthMask(false);
8736 GL_BlendFunc(GL_ONE, GL_ZERO);
8739 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8741 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8743 rsurface.texture = R_GetCurrentTexture(surface->texture);
8744 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8746 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8747 if (r_showtris.value > 0)
8749 if (!rsurface.texture->currentlayers->depthmask)
8750 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8751 else if (ent == r_refdef.scene.worldentity)
8752 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8754 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8755 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8756 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8757 R_Mesh_ColorPointer(NULL, 0, 0);
8758 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8759 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8760 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8761 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);
8762 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8765 if (r_shownormals.value < 0)
8768 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8770 VectorCopy(rsurface.vertex3f + l * 3, v);
8771 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8772 qglVertex3f(v[0], v[1], v[2]);
8773 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8774 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8775 qglVertex3f(v[0], v[1], v[2]);
8780 if (r_shownormals.value > 0)
8783 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8785 VectorCopy(rsurface.vertex3f + l * 3, v);
8786 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8787 qglVertex3f(v[0], v[1], v[2]);
8788 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8789 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8790 qglVertex3f(v[0], v[1], v[2]);
8795 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8797 VectorCopy(rsurface.vertex3f + l * 3, v);
8798 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8799 qglVertex3f(v[0], v[1], v[2]);
8800 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8801 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8802 qglVertex3f(v[0], v[1], v[2]);
8807 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8809 VectorCopy(rsurface.vertex3f + l * 3, v);
8810 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8811 qglVertex3f(v[0], v[1], v[2]);
8812 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8813 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8814 qglVertex3f(v[0], v[1], v[2]);
8821 rsurface.texture = NULL;
8825 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8826 int r_maxsurfacelist = 0;
8827 const msurface_t **r_surfacelist = NULL;
8828 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8830 int i, j, endj, f, flagsmask;
8832 dp_model_t *model = r_refdef.scene.worldmodel;
8833 msurface_t *surfaces;
8834 unsigned char *update;
8835 int numsurfacelist = 0;
8839 if (r_maxsurfacelist < model->num_surfaces)
8841 r_maxsurfacelist = model->num_surfaces;
8843 Mem_Free(r_surfacelist);
8844 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8847 RSurf_ActiveWorldEntity();
8849 surfaces = model->data_surfaces;
8850 update = model->brushq1.lightmapupdateflags;
8852 // update light styles on this submodel
8853 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8855 model_brush_lightstyleinfo_t *style;
8856 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8858 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8860 int *list = style->surfacelist;
8861 style->value = r_refdef.scene.lightstylevalue[style->style];
8862 for (j = 0;j < style->numsurfaces;j++)
8863 update[list[j]] = true;
8868 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8873 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8879 rsurface.uselightmaptexture = false;
8880 rsurface.texture = NULL;
8881 rsurface.rtlight = NULL;
8883 // add visible surfaces to draw list
8884 for (i = 0;i < model->nummodelsurfaces;i++)
8886 j = model->sortedmodelsurfaces[i];
8887 if (r_refdef.viewcache.world_surfacevisible[j])
8888 r_surfacelist[numsurfacelist++] = surfaces + j;
8890 // update lightmaps if needed
8892 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8893 if (r_refdef.viewcache.world_surfacevisible[j])
8895 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8896 // don't do anything if there were no surfaces
8897 if (!numsurfacelist)
8899 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8902 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8903 GL_AlphaTest(false);
8905 // add to stats if desired
8906 if (r_speeds.integer && !skysurfaces && !depthonly)
8908 r_refdef.stats.world_surfaces += numsurfacelist;
8909 for (j = 0;j < numsurfacelist;j++)
8910 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8913 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8916 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8918 int i, j, endj, f, flagsmask;
8920 dp_model_t *model = ent->model;
8921 msurface_t *surfaces;
8922 unsigned char *update;
8923 int numsurfacelist = 0;
8927 if (r_maxsurfacelist < model->num_surfaces)
8929 r_maxsurfacelist = model->num_surfaces;
8931 Mem_Free(r_surfacelist);
8932 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8935 // if the model is static it doesn't matter what value we give for
8936 // wantnormals and wanttangents, so this logic uses only rules applicable
8937 // to a model, knowing that they are meaningless otherwise
8938 if (ent == r_refdef.scene.worldentity)
8939 RSurf_ActiveWorldEntity();
8940 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8941 RSurf_ActiveModelEntity(ent, false, false);
8943 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8945 surfaces = model->data_surfaces;
8946 update = model->brushq1.lightmapupdateflags;
8948 // update light styles
8949 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8951 model_brush_lightstyleinfo_t *style;
8952 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8954 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8956 int *list = style->surfacelist;
8957 style->value = r_refdef.scene.lightstylevalue[style->style];
8958 for (j = 0;j < style->numsurfaces;j++)
8959 update[list[j]] = true;
8964 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8969 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8975 rsurface.uselightmaptexture = false;
8976 rsurface.texture = NULL;
8977 rsurface.rtlight = NULL;
8979 // add visible surfaces to draw list
8980 for (i = 0;i < model->nummodelsurfaces;i++)
8981 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8982 // don't do anything if there were no surfaces
8983 if (!numsurfacelist)
8985 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8988 // update lightmaps if needed
8990 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8992 R_BuildLightMap(ent, surfaces + j);
8993 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8994 GL_AlphaTest(false);
8996 // add to stats if desired
8997 if (r_speeds.integer && !skysurfaces && !depthonly)
8999 r_refdef.stats.entities_surfaces += numsurfacelist;
9000 for (j = 0;j < numsurfacelist;j++)
9001 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9004 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9007 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
9009 static texture_t texture;
9010 static msurface_t surface;
9011 const msurface_t *surfacelist = &surface;
9013 // fake enough texture and surface state to render this geometry
9015 texture.update_lastrenderframe = -1; // regenerate this texture
9016 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9017 texture.currentskinframe = skinframe;
9018 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9019 texture.specularscalemod = 1;
9020 texture.specularpowermod = 1;
9022 surface.texture = &texture;
9023 surface.num_triangles = numtriangles;
9024 surface.num_firsttriangle = firsttriangle;
9025 surface.num_vertices = numvertices;
9026 surface.num_firstvertex = firstvertex;
9029 rsurface.texture = R_GetCurrentTexture(surface.texture);
9030 rsurface.uselightmaptexture = false;
9031 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);