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"};
75 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
76 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
77 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
78 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
79 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
80 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
81 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
82 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."};
83 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
84 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
85 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
86 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."};
87 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
88 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
89 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"};
90 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"};
91 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
92 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
93 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
94 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
96 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
97 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
98 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
99 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
100 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
101 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
102 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
103 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
105 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)"};
107 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
108 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)"};
109 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
110 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
111 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
112 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
113 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)"};
114 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)"};
115 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)"};
116 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)"};
117 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)"};
119 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)"};
120 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
121 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"};
122 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
123 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
125 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
126 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
127 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
128 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
130 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
131 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
132 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
133 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
134 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
135 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
136 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
138 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
139 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
140 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
141 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)"};
143 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"};
145 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"};
147 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
149 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
150 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
151 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"};
152 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
153 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
154 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
155 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
157 extern cvar_t v_glslgamma;
159 extern qboolean v_flipped_state;
161 static struct r_bloomstate_s
166 int bloomwidth, bloomheight;
168 int screentexturewidth, screentextureheight;
169 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
171 int bloomtexturewidth, bloomtextureheight;
172 rtexture_t *texture_bloom;
174 // arrays for rendering the screen passes
175 float screentexcoord2f[8];
176 float bloomtexcoord2f[8];
177 float offsettexcoord2f[8];
179 r_viewport_t viewport;
183 r_waterstate_t r_waterstate;
185 /// shadow volume bsp struct with automatically growing nodes buffer
188 rtexture_t *r_texture_blanknormalmap;
189 rtexture_t *r_texture_white;
190 rtexture_t *r_texture_grey128;
191 rtexture_t *r_texture_black;
192 rtexture_t *r_texture_notexture;
193 rtexture_t *r_texture_whitecube;
194 rtexture_t *r_texture_normalizationcube;
195 rtexture_t *r_texture_fogattenuation;
196 rtexture_t *r_texture_gammaramps;
197 unsigned int r_texture_gammaramps_serial;
198 //rtexture_t *r_texture_fogintensity;
200 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
201 unsigned int r_numqueries;
202 unsigned int r_maxqueries;
204 typedef struct r_qwskincache_s
206 char name[MAX_QPATH];
207 skinframe_t *skinframe;
211 static r_qwskincache_t *r_qwskincache;
212 static int r_qwskincache_size;
214 /// vertex coordinates for a quad that covers the screen exactly
215 const float r_screenvertex3f[12] =
223 extern void R_DrawModelShadows(void);
225 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
228 for (i = 0;i < verts;i++)
239 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
242 for (i = 0;i < verts;i++)
252 // FIXME: move this to client?
255 if (gamemode == GAME_NEHAHRA)
257 Cvar_Set("gl_fogenable", "0");
258 Cvar_Set("gl_fogdensity", "0.2");
259 Cvar_Set("gl_fogred", "0.3");
260 Cvar_Set("gl_foggreen", "0.3");
261 Cvar_Set("gl_fogblue", "0.3");
263 r_refdef.fog_density = 0;
264 r_refdef.fog_red = 0;
265 r_refdef.fog_green = 0;
266 r_refdef.fog_blue = 0;
267 r_refdef.fog_alpha = 1;
268 r_refdef.fog_start = 0;
269 r_refdef.fog_end = 16384;
270 r_refdef.fog_height = 1<<30;
271 r_refdef.fog_fadedepth = 128;
274 static void R_BuildBlankTextures(void)
276 unsigned char data[4];
277 data[2] = 128; // normal X
278 data[1] = 128; // normal Y
279 data[0] = 255; // normal Z
280 data[3] = 128; // height
281 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
286 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
291 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
296 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
299 static void R_BuildNoTexture(void)
302 unsigned char pix[16][16][4];
303 // this makes a light grey/dark grey checkerboard texture
304 for (y = 0;y < 16;y++)
306 for (x = 0;x < 16;x++)
308 if ((y < 8) ^ (x < 8))
324 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
327 static void R_BuildWhiteCube(void)
329 unsigned char data[6*1*1*4];
330 memset(data, 255, sizeof(data));
331 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
334 static void R_BuildNormalizationCube(void)
338 vec_t s, t, intensity;
340 unsigned char data[6][NORMSIZE][NORMSIZE][4];
341 for (side = 0;side < 6;side++)
343 for (y = 0;y < NORMSIZE;y++)
345 for (x = 0;x < NORMSIZE;x++)
347 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
348 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
383 intensity = 127.0f / sqrt(DotProduct(v, v));
384 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
385 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
386 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
387 data[side][y][x][3] = 255;
391 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
394 static void R_BuildFogTexture(void)
398 unsigned char data1[FOGWIDTH][4];
399 //unsigned char data2[FOGWIDTH][4];
402 r_refdef.fogmasktable_start = r_refdef.fog_start;
403 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
404 r_refdef.fogmasktable_range = r_refdef.fogrange;
405 r_refdef.fogmasktable_density = r_refdef.fog_density;
407 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
408 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
410 d = (x * r - r_refdef.fogmasktable_start);
411 if(developer.integer >= 100)
412 Con_Printf("%f ", d);
414 if (r_fog_exp2.integer)
415 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
417 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
418 if(developer.integer >= 100)
419 Con_Printf(" : %f ", alpha);
420 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
421 if(developer.integer >= 100)
422 Con_Printf(" = %f\n", alpha);
423 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
426 for (x = 0;x < FOGWIDTH;x++)
428 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
433 //data2[x][0] = 255 - b;
434 //data2[x][1] = 255 - b;
435 //data2[x][2] = 255 - b;
438 if (r_texture_fogattenuation)
440 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
441 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
445 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);
446 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
450 static const char *builtinshaderstring =
451 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
452 "// written by Forest 'LordHavoc' Hale\n"
454 "// enable various extensions depending on permutation:\n"
456 "#ifdef USESHADOWMAPRECT\n"
457 "# extension GL_ARB_texture_rectangle : enable\n"
460 "#ifdef USESHADOWMAP2D\n"
461 "# ifdef GL_EXT_gpu_shader4\n"
462 "# extension GL_EXT_gpu_shader4 : enable\n"
464 "# ifdef GL_ARB_texture_gather\n"
465 "# extension GL_ARB_texture_gather : enable\n"
467 "# ifdef GL_AMD_texture_texture4\n"
468 "# extension GL_AMD_texture_texture4 : enable\n"
473 "#ifdef USESHADOWMAPCUBE\n"
474 "# extension GL_EXT_gpu_shader4 : enable\n"
477 "#ifdef USESHADOWSAMPLER\n"
478 "# extension GL_ARB_shadow : enable\n"
481 "// common definitions between vertex shader and fragment shader:\n"
483 "//#ifdef __GLSL_CG_DATA_TYPES\n"
484 "//# define myhalf half\n"
485 "//# define myhalf2 half2\n"
486 "//# define myhalf3half3\n"
487 "//# define myhalf4 half4\n"
489 "# define myhalf float\n"
490 "# define myhalf2 vec2\n"
491 "# define myhalf3 vec3\n"
492 "# define myhalf4 vec4\n"
495 "#ifdef USEFOGINSIDE\n"
498 "# ifdef USEFOGOUTSIDE\n"
503 "#ifdef MODE_DEPTH_OR_SHADOW\n"
505 "# ifdef VERTEX_SHADER\n"
508 " gl_Position = ftransform();\n"
513 "#ifdef MODE_SHOWDEPTH\n"
514 "# ifdef VERTEX_SHADER\n"
517 " gl_Position = ftransform();\n"
518 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
521 "# ifdef FRAGMENT_SHADER\n"
524 " gl_FragColor = gl_Color;\n"
528 "#else // !MODE_SHOWDEPTH\n"
530 "#ifdef MODE_POSTPROCESS\n"
531 "# ifdef VERTEX_SHADER\n"
534 " gl_FrontColor = gl_Color;\n"
535 " gl_Position = ftransform();\n"
536 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
538 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
542 "# ifdef FRAGMENT_SHADER\n"
544 "uniform sampler2D Texture_First;\n"
546 "uniform sampler2D Texture_Second;\n"
548 "#ifdef USEGAMMARAMPS\n"
549 "uniform sampler2D Texture_GammaRamps;\n"
551 "#ifdef USESATURATION\n"
552 "uniform float Saturation;\n"
554 "#ifdef USEVIEWTINT\n"
555 "uniform vec4 TintColor;\n"
557 "//uncomment these if you want to use them:\n"
558 "uniform vec4 UserVec1;\n"
559 "// uniform vec4 UserVec2;\n"
560 "// uniform vec4 UserVec3;\n"
561 "// uniform vec4 UserVec4;\n"
562 "// uniform float ClientTime;\n"
563 "uniform vec2 PixelSize;\n"
566 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
568 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
570 "#ifdef USEVIEWTINT\n"
571 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
574 "#ifdef USEPOSTPROCESSING\n"
575 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
576 "// 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"
577 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
578 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
579 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
580 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
581 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
582 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
585 "#ifdef USESATURATION\n"
586 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
587 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
588 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
589 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
592 "#ifdef USEGAMMARAMPS\n"
593 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
594 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
595 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
602 "#ifdef MODE_GENERIC\n"
603 "# ifdef VERTEX_SHADER\n"
606 " gl_FrontColor = gl_Color;\n"
607 "# ifdef USEDIFFUSE\n"
608 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
610 "# ifdef USESPECULAR\n"
611 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
613 " gl_Position = ftransform();\n"
616 "# ifdef FRAGMENT_SHADER\n"
618 "# ifdef USEDIFFUSE\n"
619 "uniform sampler2D Texture_First;\n"
621 "# ifdef USESPECULAR\n"
622 "uniform sampler2D Texture_Second;\n"
627 " gl_FragColor = gl_Color;\n"
628 "# ifdef USEDIFFUSE\n"
629 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
632 "# ifdef USESPECULAR\n"
633 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
635 "# ifdef USECOLORMAPPING\n"
636 " gl_FragColor *= tex2;\n"
639 " gl_FragColor += tex2;\n"
641 "# ifdef USEVERTEXTEXTUREBLEND\n"
642 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
647 "#else // !MODE_GENERIC\n"
648 "#ifdef MODE_BLOOMBLUR\n"
649 "# ifdef VERTEX_SHADER\n"
652 " gl_FrontColor = gl_Color;\n"
653 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
654 " gl_Position = ftransform();\n"
657 "# ifdef FRAGMENT_SHADER\n"
659 "uniform sampler2D Texture_First;\n"
660 "uniform vec4 BloomBlur_Parameters;\n"
665 " vec2 tc = gl_TexCoord[0].xy;\n"
666 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
667 " tc += BloomBlur_Parameters.xy;\n"
668 " for (i = 1;i < SAMPLES;i++)\n"
670 " color += texture2D(Texture_First, tc).rgb;\n"
671 " tc += BloomBlur_Parameters.xy;\n"
673 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
677 "#else // !MODE_BLOOMBLUR\n"
679 "varying vec2 TexCoord;\n"
680 "#ifdef USEVERTEXTEXTUREBLEND\n"
681 "varying vec2 TexCoord2;\n"
683 "varying vec2 TexCoordLightmap;\n"
685 "#ifdef MODE_LIGHTSOURCE\n"
686 "varying vec3 CubeVector;\n"
689 "#ifdef MODE_LIGHTSOURCE\n"
690 "varying vec3 LightVector;\n"
692 "#ifdef MODE_LIGHTDIRECTION\n"
693 "varying vec3 LightVector;\n"
696 "varying vec3 EyeVector;\n"
698 "varying vec3 EyeVectorModelSpace;\n"
699 "varying float FogPlaneVertexDist;\n"
702 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
703 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
704 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
706 "#ifdef MODE_WATER\n"
707 "varying vec4 ModelViewProjectionPosition;\n"
709 "#ifdef MODE_REFRACTION\n"
710 "varying vec4 ModelViewProjectionPosition;\n"
712 "#ifdef USEREFLECTION\n"
713 "varying vec4 ModelViewProjectionPosition;\n"
720 "// vertex shader specific:\n"
721 "#ifdef VERTEX_SHADER\n"
723 "uniform vec3 LightPosition;\n"
724 "uniform vec3 EyePosition;\n"
725 "uniform vec3 LightDir;\n"
726 "uniform vec4 FogPlane;\n"
728 "// 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"
732 " gl_FrontColor = gl_Color;\n"
733 " // copy the surface texcoord\n"
734 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
735 "#ifdef USEVERTEXTEXTUREBLEND\n"
736 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
738 "#ifndef MODE_LIGHTSOURCE\n"
739 "# ifndef MODE_LIGHTDIRECTION\n"
740 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
744 "#ifdef MODE_LIGHTSOURCE\n"
745 " // transform vertex position into light attenuation/cubemap space\n"
746 " // (-1 to +1 across the light box)\n"
747 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
749 " // transform unnormalized light direction into tangent space\n"
750 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
751 " // normalize it per pixel)\n"
752 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
753 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
754 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
755 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
758 "#ifdef MODE_LIGHTDIRECTION\n"
759 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
760 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
761 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
764 " // transform unnormalized eye direction into tangent space\n"
766 " vec3 EyeVectorModelSpace;\n"
768 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
769 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
770 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
771 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
774 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
777 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
778 " VectorS = gl_MultiTexCoord1.xyz;\n"
779 " VectorT = gl_MultiTexCoord2.xyz;\n"
780 " VectorR = gl_MultiTexCoord3.xyz;\n"
783 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
784 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
785 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
786 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
789 "// transform vertex to camera space, using ftransform to match non-VS\n"
791 " gl_Position = ftransform();\n"
793 "#ifdef MODE_WATER\n"
794 " ModelViewProjectionPosition = gl_Position;\n"
796 "#ifdef MODE_REFRACTION\n"
797 " ModelViewProjectionPosition = gl_Position;\n"
799 "#ifdef USEREFLECTION\n"
800 " ModelViewProjectionPosition = gl_Position;\n"
804 "#endif // VERTEX_SHADER\n"
809 "// fragment shader specific:\n"
810 "#ifdef FRAGMENT_SHADER\n"
812 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
813 "uniform sampler2D Texture_Normal;\n"
814 "uniform sampler2D Texture_Color;\n"
815 "uniform sampler2D Texture_Gloss;\n"
816 "uniform sampler2D Texture_Glow;\n"
817 "uniform sampler2D Texture_SecondaryNormal;\n"
818 "uniform sampler2D Texture_SecondaryColor;\n"
819 "uniform sampler2D Texture_SecondaryGloss;\n"
820 "uniform sampler2D Texture_SecondaryGlow;\n"
821 "uniform sampler2D Texture_Pants;\n"
822 "uniform sampler2D Texture_Shirt;\n"
823 "uniform sampler2D Texture_FogMask;\n"
824 "uniform sampler2D Texture_Lightmap;\n"
825 "uniform sampler2D Texture_Deluxemap;\n"
826 "uniform sampler2D Texture_Refraction;\n"
827 "uniform sampler2D Texture_Reflection;\n"
828 "uniform sampler2D Texture_Attenuation;\n"
829 "uniform samplerCube Texture_Cube;\n"
831 "#define showshadowmap 0\n"
833 "#ifdef USESHADOWMAPRECT\n"
834 "# ifdef USESHADOWSAMPLER\n"
835 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
837 "uniform sampler2DRect Texture_ShadowMapRect;\n"
841 "#ifdef USESHADOWMAP2D\n"
842 "# ifdef USESHADOWSAMPLER\n"
843 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
845 "uniform sampler2D Texture_ShadowMap2D;\n"
849 "#ifdef USESHADOWMAPVSDCT\n"
850 "uniform samplerCube Texture_CubeProjection;\n"
853 "#ifdef USESHADOWMAPCUBE\n"
854 "# ifdef USESHADOWSAMPLER\n"
855 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
857 "uniform samplerCube Texture_ShadowMapCube;\n"
861 "uniform myhalf3 LightColor;\n"
862 "uniform myhalf3 AmbientColor;\n"
863 "uniform myhalf3 DiffuseColor;\n"
864 "uniform myhalf3 SpecularColor;\n"
865 "uniform myhalf3 Color_Pants;\n"
866 "uniform myhalf3 Color_Shirt;\n"
867 "uniform myhalf3 FogColor;\n"
869 "uniform myhalf4 TintColor;\n"
872 "//#ifdef MODE_WATER\n"
873 "uniform vec4 DistortScaleRefractReflect;\n"
874 "uniform vec4 ScreenScaleRefractReflect;\n"
875 "uniform vec4 ScreenCenterRefractReflect;\n"
876 "uniform myhalf4 RefractColor;\n"
877 "uniform myhalf4 ReflectColor;\n"
878 "uniform myhalf ReflectFactor;\n"
879 "uniform myhalf ReflectOffset;\n"
881 "//# ifdef MODE_REFRACTION\n"
882 "//uniform vec4 DistortScaleRefractReflect;\n"
883 "//uniform vec4 ScreenScaleRefractReflect;\n"
884 "//uniform vec4 ScreenCenterRefractReflect;\n"
885 "//uniform myhalf4 RefractColor;\n"
886 "//# ifdef USEREFLECTION\n"
887 "//uniform myhalf4 ReflectColor;\n"
890 "//# ifdef USEREFLECTION\n"
891 "//uniform vec4 DistortScaleRefractReflect;\n"
892 "//uniform vec4 ScreenScaleRefractReflect;\n"
893 "//uniform vec4 ScreenCenterRefractReflect;\n"
894 "//uniform myhalf4 ReflectColor;\n"
899 "uniform myhalf3 GlowColor;\n"
900 "uniform myhalf SceneBrightness;\n"
902 "uniform float OffsetMapping_Scale;\n"
903 "uniform float OffsetMapping_Bias;\n"
904 "uniform float FogRangeRecip;\n"
905 "uniform float FogPlaneViewDist;\n"
906 "uniform float FogHeightFade;\n"
908 "uniform myhalf AmbientScale;\n"
909 "uniform myhalf DiffuseScale;\n"
910 "uniform myhalf SpecularScale;\n"
911 "uniform myhalf SpecularPower;\n"
913 "#ifdef USEOFFSETMAPPING\n"
914 "vec2 OffsetMapping(vec2 TexCoord)\n"
916 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
917 " // 14 sample relief mapping: linear search and then binary search\n"
918 " // this basically steps forward a small amount repeatedly until it finds\n"
919 " // itself inside solid, then jitters forward and back using decreasing\n"
920 " // amounts to find the impact\n"
921 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
922 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
923 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
924 " vec3 RT = vec3(TexCoord, 1);\n"
925 " OffsetVector *= 0.1;\n"
926 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
936 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
937 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
938 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
939 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
942 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
943 " // this basically moves forward the full distance, and then backs up based\n"
944 " // on height of samples\n"
945 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
946 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
947 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
948 " TexCoord += OffsetVector;\n"
949 " OffsetVector *= 0.333;\n"
950 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
951 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
952 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
953 " return TexCoord;\n"
956 "#endif // USEOFFSETMAPPING\n"
958 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
959 "uniform vec2 ShadowMap_TextureScale;\n"
960 "uniform vec4 ShadowMap_Parameters;\n"
963 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
964 "vec3 GetShadowMapTC2D(vec3 dir)\n"
966 " vec3 adir = abs(dir);\n"
967 "# ifndef USESHADOWMAPVSDCT\n"
971 " if (adir.x > adir.y)\n"
973 " if (adir.x > adir.z) // X\n"
977 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
983 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
988 " if (adir.y > adir.z) // Y\n"
992 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
998 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1002 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1003 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1004 " stc.z += ShadowMap_Parameters.z;\n"
1005 "# if showshadowmap\n"
1006 " stc.xy *= ShadowMap_TextureScale;\n"
1010 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1011 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1012 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1013 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1014 " stc.z += ShadowMap_Parameters.z;\n"
1015 "# if showshadowmap\n"
1016 " stc.xy *= ShadowMap_TextureScale;\n"
1021 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1023 "#ifdef USESHADOWMAPCUBE\n"
1024 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1026 " vec3 adir = abs(dir);\n"
1027 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1031 "#if !showshadowmap\n"
1032 "# ifdef USESHADOWMAPRECT\n"
1033 "float ShadowMapCompare(vec3 dir)\n"
1035 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1037 "# ifdef USESHADOWSAMPLER\n"
1039 "# ifdef USESHADOWMAPPCF\n"
1040 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1041 " 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"
1043 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1048 "# ifdef USESHADOWMAPPCF\n"
1049 "# if USESHADOWMAPPCF > 1\n"
1050 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1051 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1052 " 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"
1053 " 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"
1054 " 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"
1055 " 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"
1056 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1057 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1059 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1060 " vec2 offset = fract(shadowmaptc.xy);\n"
1061 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1062 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1063 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1064 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1065 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1068 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1076 "# ifdef USESHADOWMAP2D\n"
1077 "float ShadowMapCompare(vec3 dir)\n"
1079 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1082 "# ifdef USESHADOWSAMPLER\n"
1083 "# ifdef USESHADOWMAPPCF\n"
1084 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1085 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1086 " 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"
1088 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1091 "# ifdef USESHADOWMAPPCF\n"
1092 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1093 "# ifdef GL_ARB_texture_gather\n"
1094 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1096 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1098 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1099 " center *= ShadowMap_TextureScale;\n"
1100 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1101 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1102 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1103 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1104 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1105 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1106 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1108 "# ifdef GL_EXT_gpu_shader4\n"
1109 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1111 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1113 "# if USESHADOWMAPPCF > 1\n"
1114 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1115 " center *= ShadowMap_TextureScale;\n"
1116 " 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"
1117 " 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"
1118 " 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"
1119 " 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"
1120 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1121 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1123 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1124 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1125 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1126 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1127 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1128 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1132 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1139 "# ifdef USESHADOWMAPCUBE\n"
1140 "float ShadowMapCompare(vec3 dir)\n"
1142 " // apply depth texture cubemap as light filter\n"
1143 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1145 "# ifdef USESHADOWSAMPLER\n"
1146 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1148 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1155 "#ifdef MODE_WATER\n"
1160 "#ifdef USEOFFSETMAPPING\n"
1161 " // apply offsetmapping\n"
1162 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1163 "#define TexCoord TexCoordOffset\n"
1166 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1167 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1168 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1169 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1170 " // FIXME temporary hack to detect the case that the reflection\n"
1171 " // gets blackened at edges due to leaving the area that contains actual\n"
1173 " // Remove this 'ack once we have a better way to stop this thing from\n"
1175 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1176 " 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 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1180 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\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 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1185 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1186 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1189 "#else // !MODE_WATER\n"
1190 "#ifdef MODE_REFRACTION\n"
1192 "// refraction pass\n"
1195 "#ifdef USEOFFSETMAPPING\n"
1196 " // apply offsetmapping\n"
1197 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1198 "#define TexCoord TexCoordOffset\n"
1201 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1202 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1203 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1204 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1205 " // FIXME temporary hack to detect the case that the reflection\n"
1206 " // gets blackened at edges due to leaving the area that contains actual\n"
1208 " // Remove this 'ack once we have a better way to stop this thing from\n"
1210 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1211 " 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 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1215 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1218 "#else // !MODE_REFRACTION\n"
1221 "#ifdef USEOFFSETMAPPING\n"
1222 " // apply offsetmapping\n"
1223 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1224 "#define TexCoord TexCoordOffset\n"
1227 " // combine the diffuse textures (base, pants, shirt)\n"
1228 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1229 "#ifdef USECOLORMAPPING\n"
1230 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1232 "#ifdef USEVERTEXTEXTUREBLEND\n"
1233 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1234 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1235 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1236 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1238 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1241 "#ifdef USEDIFFUSE\n"
1242 " // get the surface normal and the gloss color\n"
1243 "# ifdef USEVERTEXTEXTUREBLEND\n"
1244 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1245 "# ifdef USESPECULAR\n"
1246 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1249 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1250 "# ifdef USESPECULAR\n"
1251 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1258 "#ifdef MODE_LIGHTSOURCE\n"
1259 " // light source\n"
1261 " // calculate surface normal, light normal, and specular normal\n"
1262 " // compute color intensity for the two textures (colormap and glossmap)\n"
1263 " // scale by light color and attenuation as efficiently as possible\n"
1264 " // (do as much scalar math as possible rather than vector math)\n"
1265 "# ifdef USEDIFFUSE\n"
1266 " // get the light normal\n"
1267 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1269 "# ifdef USESPECULAR\n"
1270 "# ifndef USEEXACTSPECULARMATH\n"
1271 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1274 " // calculate directional shading\n"
1275 "# ifdef USEEXACTSPECULARMATH\n"
1276 " 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"
1278 " 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"
1281 "# ifdef USEDIFFUSE\n"
1282 " // calculate directional shading\n"
1283 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1285 " // calculate directionless shading\n"
1286 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1290 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1291 "#if !showshadowmap\n"
1292 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1296 "# ifdef USECUBEFILTER\n"
1297 " // apply light cubemap filter\n"
1298 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1299 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1301 "#endif // MODE_LIGHTSOURCE\n"
1306 "#ifdef MODE_LIGHTDIRECTION\n"
1307 " // directional model lighting\n"
1308 "# ifdef USEDIFFUSE\n"
1309 " // get the light normal\n"
1310 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1312 "# ifdef USESPECULAR\n"
1313 " // calculate directional shading\n"
1314 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1315 "# ifdef USEEXACTSPECULARMATH\n"
1316 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1318 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1319 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1322 "# ifdef USEDIFFUSE\n"
1324 " // calculate directional shading\n"
1325 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1327 " color.rgb *= AmbientColor;\n"
1330 "#endif // MODE_LIGHTDIRECTION\n"
1335 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1336 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1338 " // get the light normal\n"
1339 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1340 " myhalf3 diffusenormal;\n"
1341 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1342 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1343 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1344 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1345 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1346 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1347 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1348 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1349 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1350 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1351 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1352 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1353 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1354 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1355 "# ifdef USESPECULAR\n"
1356 "# ifdef USEEXACTSPECULARMATH\n"
1357 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1359 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1360 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1364 " // apply lightmap color\n"
1365 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1366 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1371 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1372 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1374 " // get the light normal\n"
1375 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1376 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1377 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1378 "# ifdef USESPECULAR\n"
1379 "# ifdef USEEXACTSPECULARMATH\n"
1380 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1382 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1383 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1387 " // apply lightmap color\n"
1388 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1389 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1394 "#ifdef MODE_LIGHTMAP\n"
1395 " // apply lightmap color\n"
1396 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1397 "#endif // MODE_LIGHTMAP\n"
1402 "#ifdef MODE_VERTEXCOLOR\n"
1403 " // apply lightmap color\n"
1404 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1405 "#endif // MODE_VERTEXCOLOR\n"
1410 "#ifdef MODE_FLATCOLOR\n"
1411 "#endif // MODE_FLATCOLOR\n"
1419 " color *= TintColor;\n"
1422 "#ifdef USEVERTEXTEXTUREBLEND\n"
1423 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1425 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1429 " color.rgb *= SceneBrightness;\n"
1431 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1434 "#ifdef USEFOGOUTSIDE\n"
1435 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1437 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1439 "// float FogHeightFade1 = -0.5/1024.0;\n"
1440 "// if (FogPlaneViewDist >= 0.0)\n"
1441 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade1);\n"
1443 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade1);\n"
1444 "//# ifdef USEFOGABOVE\n"
1445 "// if (FogPlaneViewDist >= 0.0)\n"
1446 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist);\n"
1448 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist));\n"
1449 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1450 "// fogfrac *= min(1.0, (max(0.0, fade*FogPlaneVertexDist) + max(0.0, fade*FogPlaneViewDist)));\n"
1451 "// fogfrac *= min(1.0, (max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1452 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1454 " //fogfrac *= min(1.0, max(0.0, (max(-2048, min(0, FogPlaneVertexDist)) + max(-2048, min(0, FogPlaneViewDist)))/-2048.0));\n"
1455 " //float fade = -0.5/128.0;\n"
1456 " //fogfrac *= max(0.0, min(1.0, fade*FogPlaneVertexDist)) + max(0.0, min(1.0, fade*FogPlaneViewDist));\n"
1457 " //fogfrac *= max(0.0, min(1.0, FogHeightFade1*FogPlaneVertexDist)) + max(0.0, min(1.0, FogHeightFade1*FogPlaneViewDist));\n"
1458 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1459 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1460 " //fogfrac *= min(1.0, min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1461 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1462 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1463 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1465 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0))));\n"
1468 " // 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"
1469 "#ifdef USEREFLECTION\n"
1470 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1471 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1472 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1473 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1474 " // FIXME temporary hack to detect the case that the reflection\n"
1475 " // gets blackened at edges due to leaving the area that contains actual\n"
1477 " // Remove this 'ack once we have a better way to stop this thing from\n"
1479 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1480 " 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 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1484 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1487 " gl_FragColor = vec4(color);\n"
1489 "#if showshadowmap\n"
1490 "# ifdef USESHADOWMAPRECT\n"
1491 "# ifdef USESHADOWSAMPLER\n"
1492 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1494 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1497 "# ifdef USESHADOWMAP2D\n"
1498 "# ifdef USESHADOWSAMPLER\n"
1499 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1501 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1505 "# ifdef USESHADOWMAPCUBE\n"
1506 "# ifdef USESHADOWSAMPLER\n"
1507 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1509 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1514 "#endif // !MODE_REFRACTION\n"
1515 "#endif // !MODE_WATER\n"
1517 "#endif // FRAGMENT_SHADER\n"
1519 "#endif // !MODE_BLOOMBLUR\n"
1520 "#endif // !MODE_GENERIC\n"
1521 "#endif // !MODE_POSTPROCESS\n"
1522 "#endif // !MODE_SHOWDEPTH\n"
1523 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1526 typedef struct shaderpermutationinfo_s
1528 const char *pretext;
1531 shaderpermutationinfo_t;
1533 typedef struct shadermodeinfo_s
1535 const char *vertexfilename;
1536 const char *geometryfilename;
1537 const char *fragmentfilename;
1538 const char *pretext;
1543 typedef enum shaderpermutation_e
1545 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1546 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1547 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1548 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1549 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1550 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1551 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1552 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1553 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1554 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1555 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1556 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1557 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1558 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1559 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1560 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1561 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1562 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1563 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1564 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1565 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1566 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1567 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1568 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1569 SHADERPERMUTATION_LIMIT = 1<<24, ///< size of permutations array
1570 SHADERPERMUTATION_COUNT = 24 ///< size of shaderpermutationinfo array
1572 shaderpermutation_t;
1574 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1575 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1577 {"#define USEDIFFUSE\n", " diffuse"},
1578 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1579 {"#define USEVIEWTINT\n", " viewtint"},
1580 {"#define USECOLORMAPPING\n", " colormapping"},
1581 {"#define USESATURATION\n", " saturation"},
1582 {"#define USEFOGINSIDE\n", " foginside"},
1583 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1584 {"#define USEGAMMARAMPS\n", " gammaramps"},
1585 {"#define USECUBEFILTER\n", " cubefilter"},
1586 {"#define USEGLOW\n", " glow"},
1587 {"#define USEBLOOM\n", " bloom"},
1588 {"#define USESPECULAR\n", " specular"},
1589 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1590 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1591 {"#define USEREFLECTION\n", " reflection"},
1592 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1593 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1594 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1595 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1596 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1597 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1598 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1599 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1600 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1603 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1604 typedef enum shadermode_e
1606 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1607 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1608 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1609 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1610 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1611 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1612 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1613 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1614 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1615 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1616 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1617 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1618 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1623 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1624 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1626 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1627 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1628 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1629 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1630 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1631 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1632 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1633 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1634 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1635 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1636 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1637 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1638 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1641 struct r_glsl_permutation_s;
1642 typedef struct r_glsl_permutation_s
1644 /// hash lookup data
1645 struct r_glsl_permutation_s *hashnext;
1647 unsigned int permutation;
1649 /// indicates if we have tried compiling this permutation already
1651 /// 0 if compilation failed
1653 /// locations of detected uniforms in program object, or -1 if not found
1654 int loc_Texture_First;
1655 int loc_Texture_Second;
1656 int loc_Texture_GammaRamps;
1657 int loc_Texture_Normal;
1658 int loc_Texture_Color;
1659 int loc_Texture_Gloss;
1660 int loc_Texture_Glow;
1661 int loc_Texture_SecondaryNormal;
1662 int loc_Texture_SecondaryColor;
1663 int loc_Texture_SecondaryGloss;
1664 int loc_Texture_SecondaryGlow;
1665 int loc_Texture_Pants;
1666 int loc_Texture_Shirt;
1667 int loc_Texture_FogMask;
1668 int loc_Texture_Lightmap;
1669 int loc_Texture_Deluxemap;
1670 int loc_Texture_Attenuation;
1671 int loc_Texture_Cube;
1672 int loc_Texture_Refraction;
1673 int loc_Texture_Reflection;
1674 int loc_Texture_ShadowMapRect;
1675 int loc_Texture_ShadowMapCube;
1676 int loc_Texture_ShadowMap2D;
1677 int loc_Texture_CubeProjection;
1679 int loc_LightPosition;
1680 int loc_EyePosition;
1681 int loc_Color_Pants;
1682 int loc_Color_Shirt;
1684 int loc_FogPlaneViewDist;
1685 int loc_FogRangeRecip;
1686 int loc_FogHeightFade;
1687 int loc_AmbientScale;
1688 int loc_DiffuseScale;
1689 int loc_SpecularScale;
1690 int loc_SpecularPower;
1692 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1693 int loc_OffsetMapping_Scale;
1695 int loc_AmbientColor;
1696 int loc_DiffuseColor;
1697 int loc_SpecularColor;
1699 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1700 int loc_GammaCoeff; ///< 1 / gamma
1701 int loc_DistortScaleRefractReflect;
1702 int loc_ScreenScaleRefractReflect;
1703 int loc_ScreenCenterRefractReflect;
1704 int loc_RefractColor;
1705 int loc_ReflectColor;
1706 int loc_ReflectFactor;
1707 int loc_ReflectOffset;
1715 int loc_ShadowMap_TextureScale;
1716 int loc_ShadowMap_Parameters;
1718 r_glsl_permutation_t;
1720 #define SHADERPERMUTATION_HASHSIZE 256
1722 /// information about each possible shader permutation
1723 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1724 /// currently selected permutation
1725 r_glsl_permutation_t *r_glsl_permutation;
1726 /// storage for permutations linked in the hash table
1727 memexpandablearray_t r_glsl_permutationarray;
1729 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1731 //unsigned int hashdepth = 0;
1732 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1733 r_glsl_permutation_t *p;
1734 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1736 if (p->mode == mode && p->permutation == permutation)
1738 //if (hashdepth > 10)
1739 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1744 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1746 p->permutation = permutation;
1747 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1748 r_glsl_permutationhash[mode][hashindex] = p;
1749 //if (hashdepth > 10)
1750 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1754 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1757 if (!filename || !filename[0])
1759 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1762 if (printfromdisknotice)
1763 Con_DPrint("from disk... ");
1764 return shaderstring;
1766 else if (!strcmp(filename, "glsl/default.glsl"))
1768 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1769 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1771 return shaderstring;
1774 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1777 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1778 int vertstrings_count = 0;
1779 int geomstrings_count = 0;
1780 int fragstrings_count = 0;
1781 char *vertexstring, *geometrystring, *fragmentstring;
1782 const char *vertstrings_list[32+3];
1783 const char *geomstrings_list[32+3];
1784 const char *fragstrings_list[32+3];
1785 char permutationname[256];
1792 permutationname[0] = 0;
1793 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1794 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1795 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1797 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1799 // the first pretext is which type of shader to compile as
1800 // (later these will all be bound together as a program object)
1801 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1802 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1803 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1805 // the second pretext is the mode (for example a light source)
1806 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1807 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1808 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1809 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1811 // now add all the permutation pretexts
1812 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1814 if (permutation & (1<<i))
1816 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1817 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1818 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1819 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1823 // keep line numbers correct
1824 vertstrings_list[vertstrings_count++] = "\n";
1825 geomstrings_list[geomstrings_count++] = "\n";
1826 fragstrings_list[fragstrings_count++] = "\n";
1830 // now append the shader text itself
1831 vertstrings_list[vertstrings_count++] = vertexstring;
1832 geomstrings_list[geomstrings_count++] = geometrystring;
1833 fragstrings_list[fragstrings_count++] = fragmentstring;
1835 // if any sources were NULL, clear the respective list
1837 vertstrings_count = 0;
1838 if (!geometrystring)
1839 geomstrings_count = 0;
1840 if (!fragmentstring)
1841 fragstrings_count = 0;
1843 // compile the shader program
1844 if (vertstrings_count + geomstrings_count + fragstrings_count)
1845 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1849 qglUseProgramObjectARB(p->program);CHECKGLERROR
1850 // look up all the uniform variable names we care about, so we don't
1851 // have to look them up every time we set them
1852 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1853 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1854 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1855 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1856 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1857 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1858 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1859 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1860 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1861 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1862 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1863 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1864 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1865 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1866 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1867 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1868 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1869 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1870 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1871 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1872 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1873 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1874 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1875 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1876 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1877 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1878 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1879 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1880 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1881 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
1882 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
1883 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1884 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
1885 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1886 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1887 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1888 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1889 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1890 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1891 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1892 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1893 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1894 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1895 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1896 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1897 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1898 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1899 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1900 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1901 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1902 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1903 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1904 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1905 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1906 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1907 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1908 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1909 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1910 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1911 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1912 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1913 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1914 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1915 // initialize the samplers to refer to the texture units we use
1916 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1917 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1918 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1919 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1920 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1921 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1922 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1923 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1924 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1925 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1926 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1927 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1928 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1929 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1930 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1931 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1932 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1933 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1934 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1935 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1936 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1937 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1938 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1939 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1941 if (developer.integer)
1942 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1945 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1949 Mem_Free(vertexstring);
1951 Mem_Free(geometrystring);
1953 Mem_Free(fragmentstring);
1956 void R_GLSL_Restart_f(void)
1958 unsigned int i, limit;
1959 r_glsl_permutation_t *p;
1960 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1961 for (i = 0;i < limit;i++)
1963 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1965 GL_Backend_FreeProgram(p->program);
1966 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1969 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1972 void R_GLSL_DumpShader_f(void)
1976 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1979 Con_Printf("failed to write to glsl/default.glsl\n");
1983 FS_Print(file, "/* The engine may define the following macros:\n");
1984 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1985 for (i = 0;i < SHADERMODE_COUNT;i++)
1986 FS_Print(file, shadermodeinfo[i].pretext);
1987 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1988 FS_Print(file, shaderpermutationinfo[i].pretext);
1989 FS_Print(file, "*/\n");
1990 FS_Print(file, builtinshaderstring);
1993 Con_Printf("glsl/default.glsl written\n");
1996 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1998 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1999 if (r_glsl_permutation != perm)
2001 r_glsl_permutation = perm;
2002 if (!r_glsl_permutation->program)
2004 if (!r_glsl_permutation->compiled)
2005 R_GLSL_CompilePermutation(perm, mode, permutation);
2006 if (!r_glsl_permutation->program)
2008 // remove features until we find a valid permutation
2010 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2012 // reduce i more quickly whenever it would not remove any bits
2013 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2014 if (!(permutation & j))
2017 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2018 if (!r_glsl_permutation->compiled)
2019 R_GLSL_CompilePermutation(perm, mode, permutation);
2020 if (r_glsl_permutation->program)
2023 if (i >= SHADERPERMUTATION_COUNT)
2025 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");
2026 Cvar_SetValueQuick(&r_glsl, 0);
2027 R_GLSL_Restart_f(); // unload shaders
2028 return; // no bit left to clear
2033 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2037 void R_SetupGenericShader(qboolean usetexture)
2039 if (gl_support_fragment_shader)
2041 if (r_glsl.integer && r_glsl_usegeneric.integer)
2042 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2043 else if (r_glsl_permutation)
2045 r_glsl_permutation = NULL;
2046 qglUseProgramObjectARB(0);CHECKGLERROR
2051 void R_SetupGenericTwoTextureShader(int texturemode)
2053 if (gl_support_fragment_shader)
2055 if (r_glsl.integer && r_glsl_usegeneric.integer)
2056 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))));
2057 else if (r_glsl_permutation)
2059 r_glsl_permutation = NULL;
2060 qglUseProgramObjectARB(0);CHECKGLERROR
2063 if (!r_glsl_permutation)
2065 if (texturemode == GL_DECAL && gl_combine.integer)
2066 texturemode = GL_INTERPOLATE_ARB;
2067 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
2071 void R_SetupDepthOrShadowShader(void)
2073 if (gl_support_fragment_shader)
2075 if (r_glsl.integer && r_glsl_usegeneric.integer)
2076 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2077 else if (r_glsl_permutation)
2079 r_glsl_permutation = NULL;
2080 qglUseProgramObjectARB(0);CHECKGLERROR
2085 void R_SetupShowDepthShader(void)
2087 if (gl_support_fragment_shader)
2089 if (r_glsl.integer && r_glsl_usegeneric.integer)
2090 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2091 else if (r_glsl_permutation)
2093 r_glsl_permutation = NULL;
2094 qglUseProgramObjectARB(0);CHECKGLERROR
2099 extern rtexture_t *r_shadow_attenuationgradienttexture;
2100 extern rtexture_t *r_shadow_attenuation2dtexture;
2101 extern rtexture_t *r_shadow_attenuation3dtexture;
2102 extern qboolean r_shadow_usingshadowmaprect;
2103 extern qboolean r_shadow_usingshadowmapcube;
2104 extern qboolean r_shadow_usingshadowmap2d;
2105 extern float r_shadow_shadowmap_texturescale[2];
2106 extern float r_shadow_shadowmap_parameters[4];
2107 extern qboolean r_shadow_shadowmapvsdct;
2108 extern qboolean r_shadow_shadowmapsampler;
2109 extern int r_shadow_shadowmappcf;
2110 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2112 // select a permutation of the lighting shader appropriate to this
2113 // combination of texture, entity, light source, and fogging, only use the
2114 // minimum features necessary to avoid wasting rendering time in the
2115 // fragment shader on features that are not being used
2116 unsigned int permutation = 0;
2117 unsigned int mode = 0;
2118 // TODO: implement geometry-shader based shadow volumes someday
2119 if (r_glsl_offsetmapping.integer)
2121 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2122 if (r_glsl_offsetmapping_reliefmapping.integer)
2123 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2125 if (rsurfacepass == RSURFPASS_BACKGROUND)
2127 // distorted background
2128 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2129 mode = SHADERMODE_WATER;
2131 mode = SHADERMODE_REFRACTION;
2133 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2136 mode = SHADERMODE_LIGHTSOURCE;
2137 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2138 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2139 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2140 permutation |= SHADERPERMUTATION_CUBEFILTER;
2141 if (diffusescale > 0)
2142 permutation |= SHADERPERMUTATION_DIFFUSE;
2143 if (specularscale > 0)
2144 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2145 if (r_refdef.fogenabled)
2146 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2147 if (rsurface.texture->colormapping)
2148 permutation |= SHADERPERMUTATION_COLORMAPPING;
2149 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2151 if (r_shadow_usingshadowmaprect)
2152 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2153 if (r_shadow_usingshadowmap2d)
2154 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2155 if (r_shadow_usingshadowmapcube)
2156 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2157 else if(r_shadow_shadowmapvsdct)
2158 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2160 if (r_shadow_shadowmapsampler)
2161 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2162 if (r_shadow_shadowmappcf > 1)
2163 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2164 else if (r_shadow_shadowmappcf)
2165 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2168 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2170 // unshaded geometry (fullbright or ambient model lighting)
2171 mode = SHADERMODE_FLATCOLOR;
2172 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2173 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2174 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2175 permutation |= SHADERPERMUTATION_GLOW;
2176 if (r_refdef.fogenabled)
2177 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2178 if (rsurface.texture->colormapping)
2179 permutation |= SHADERPERMUTATION_COLORMAPPING;
2180 if (r_glsl_offsetmapping.integer)
2182 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2183 if (r_glsl_offsetmapping_reliefmapping.integer)
2184 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2186 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2187 permutation |= SHADERPERMUTATION_REFLECTION;
2189 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2191 // directional model lighting
2192 mode = SHADERMODE_LIGHTDIRECTION;
2193 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2194 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2195 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2196 permutation |= SHADERPERMUTATION_GLOW;
2197 permutation |= SHADERPERMUTATION_DIFFUSE;
2198 if (specularscale > 0)
2199 permutation |= SHADERPERMUTATION_SPECULAR;
2200 if (r_refdef.fogenabled)
2201 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2202 if (rsurface.texture->colormapping)
2203 permutation |= SHADERPERMUTATION_COLORMAPPING;
2204 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2205 permutation |= SHADERPERMUTATION_REFLECTION;
2207 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2209 // ambient model lighting
2210 mode = SHADERMODE_LIGHTDIRECTION;
2211 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2212 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2213 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2214 permutation |= SHADERPERMUTATION_GLOW;
2215 if (r_refdef.fogenabled)
2216 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2217 if (rsurface.texture->colormapping)
2218 permutation |= SHADERPERMUTATION_COLORMAPPING;
2219 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2220 permutation |= SHADERPERMUTATION_REFLECTION;
2225 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2227 // deluxemapping (light direction texture)
2228 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2229 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2231 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2232 permutation |= SHADERPERMUTATION_DIFFUSE;
2233 if (specularscale > 0)
2234 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2236 else if (r_glsl_deluxemapping.integer >= 2)
2238 // fake deluxemapping (uniform light direction in tangentspace)
2239 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2240 permutation |= SHADERPERMUTATION_DIFFUSE;
2241 if (specularscale > 0)
2242 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2244 else if (rsurface.uselightmaptexture)
2246 // ordinary lightmapping (q1bsp, q3bsp)
2247 mode = SHADERMODE_LIGHTMAP;
2251 // ordinary vertex coloring (q3bsp)
2252 mode = SHADERMODE_VERTEXCOLOR;
2254 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2255 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2256 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2257 permutation |= SHADERPERMUTATION_GLOW;
2258 if (r_refdef.fogenabled)
2259 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2260 if (rsurface.texture->colormapping)
2261 permutation |= SHADERPERMUTATION_COLORMAPPING;
2262 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2263 permutation |= SHADERPERMUTATION_REFLECTION;
2265 if(permutation & SHADERPERMUTATION_SPECULAR)
2266 if(r_shadow_glossexact.integer)
2267 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2268 R_SetupShader_SetPermutation(mode, permutation);
2269 if (mode == SHADERMODE_LIGHTSOURCE)
2271 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2272 if (permutation & SHADERPERMUTATION_DIFFUSE)
2274 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2275 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2276 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2277 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2281 // ambient only is simpler
2282 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]);
2283 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2284 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2285 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2287 // additive passes are only darkened by fog, not tinted
2288 if (r_glsl_permutation->loc_FogColor >= 0)
2289 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2290 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]);
2291 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]);
2295 if (mode == SHADERMODE_LIGHTDIRECTION)
2297 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);
2298 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);
2299 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);
2300 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]);
2304 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2305 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2306 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2308 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]);
2309 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);
2310 // additive passes are only darkened by fog, not tinted
2311 if (r_glsl_permutation->loc_FogColor >= 0)
2313 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2314 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2316 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2318 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);
2319 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]);
2320 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]);
2321 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2322 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2323 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2324 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2326 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2327 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2328 if (r_glsl_permutation->loc_Color_Pants >= 0)
2330 if (rsurface.texture->currentskinframe->pants)
2331 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2333 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2335 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2337 if (rsurface.texture->currentskinframe->shirt)
2338 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2340 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2342 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]);
2343 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2344 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2345 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2346 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2348 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2352 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2354 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2358 #define SKINFRAME_HASH 1024
2362 int loadsequence; // incremented each level change
2363 memexpandablearray_t array;
2364 skinframe_t *hash[SKINFRAME_HASH];
2367 r_skinframe_t r_skinframe;
2369 void R_SkinFrame_PrepareForPurge(void)
2371 r_skinframe.loadsequence++;
2372 // wrap it without hitting zero
2373 if (r_skinframe.loadsequence >= 200)
2374 r_skinframe.loadsequence = 1;
2377 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2381 // mark the skinframe as used for the purging code
2382 skinframe->loadsequence = r_skinframe.loadsequence;
2385 void R_SkinFrame_Purge(void)
2389 for (i = 0;i < SKINFRAME_HASH;i++)
2391 for (s = r_skinframe.hash[i];s;s = s->next)
2393 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2395 if (s->merged == s->base)
2397 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2398 R_PurgeTexture(s->stain );s->stain = NULL;
2399 R_PurgeTexture(s->merged);s->merged = NULL;
2400 R_PurgeTexture(s->base );s->base = NULL;
2401 R_PurgeTexture(s->pants );s->pants = NULL;
2402 R_PurgeTexture(s->shirt );s->shirt = NULL;
2403 R_PurgeTexture(s->nmap );s->nmap = NULL;
2404 R_PurgeTexture(s->gloss );s->gloss = NULL;
2405 R_PurgeTexture(s->glow );s->glow = NULL;
2406 R_PurgeTexture(s->fog );s->fog = NULL;
2407 s->loadsequence = 0;
2413 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2415 char basename[MAX_QPATH];
2417 Image_StripImageExtension(name, basename, sizeof(basename));
2419 if( last == NULL ) {
2421 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2422 item = r_skinframe.hash[hashindex];
2427 // linearly search through the hash bucket
2428 for( ; item ; item = item->next ) {
2429 if( !strcmp( item->basename, basename ) ) {
2436 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2440 char basename[MAX_QPATH];
2442 Image_StripImageExtension(name, basename, sizeof(basename));
2444 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2445 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2446 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2450 rtexture_t *dyntexture;
2451 // check whether its a dynamic texture
2452 dyntexture = CL_GetDynTexture( basename );
2453 if (!add && !dyntexture)
2455 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2456 memset(item, 0, sizeof(*item));
2457 strlcpy(item->basename, basename, sizeof(item->basename));
2458 item->base = dyntexture; // either NULL or dyntexture handle
2459 item->textureflags = textureflags;
2460 item->comparewidth = comparewidth;
2461 item->compareheight = compareheight;
2462 item->comparecrc = comparecrc;
2463 item->next = r_skinframe.hash[hashindex];
2464 r_skinframe.hash[hashindex] = item;
2466 else if( item->base == NULL )
2468 rtexture_t *dyntexture;
2469 // check whether its a dynamic texture
2470 // 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]
2471 dyntexture = CL_GetDynTexture( basename );
2472 item->base = dyntexture; // either NULL or dyntexture handle
2475 R_SkinFrame_MarkUsed(item);
2479 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2481 unsigned long long avgcolor[5], wsum; \
2489 for(pix = 0; pix < cnt; ++pix) \
2492 for(comp = 0; comp < 3; ++comp) \
2494 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2497 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2499 for(comp = 0; comp < 3; ++comp) \
2500 avgcolor[comp] += getpixel * w; \
2503 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2504 avgcolor[4] += getpixel; \
2506 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2508 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2509 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2510 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2511 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2514 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2516 // FIXME: it should be possible to disable loading various layers using
2517 // cvars, to prevent wasted loading time and memory usage if the user does
2519 qboolean loadnormalmap = true;
2520 qboolean loadgloss = true;
2521 qboolean loadpantsandshirt = true;
2522 qboolean loadglow = true;
2524 unsigned char *pixels;
2525 unsigned char *bumppixels;
2526 unsigned char *basepixels = NULL;
2527 int basepixels_width;
2528 int basepixels_height;
2529 skinframe_t *skinframe;
2534 if (cls.state == ca_dedicated)
2537 // return an existing skinframe if already loaded
2538 // if loading of the first image fails, don't make a new skinframe as it
2539 // would cause all future lookups of this to be missing
2540 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2541 if (skinframe && skinframe->base)
2544 basepixels = loadimagepixelsbgra(name, complain, true);
2545 if (basepixels == NULL)
2548 if (developer_loading.integer)
2549 Con_Printf("loading skin \"%s\"\n", name);
2551 // we've got some pixels to store, so really allocate this new texture now
2553 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2554 skinframe->stain = NULL;
2555 skinframe->merged = NULL;
2556 skinframe->base = r_texture_notexture;
2557 skinframe->pants = NULL;
2558 skinframe->shirt = NULL;
2559 skinframe->nmap = r_texture_blanknormalmap;
2560 skinframe->gloss = NULL;
2561 skinframe->glow = NULL;
2562 skinframe->fog = NULL;
2564 basepixels_width = image_width;
2565 basepixels_height = image_height;
2566 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);
2568 if (textureflags & TEXF_ALPHA)
2570 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2571 if (basepixels[j] < 255)
2573 if (j < basepixels_width * basepixels_height * 4)
2575 // has transparent pixels
2578 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2579 for (j = 0;j < image_width * image_height * 4;j += 4)
2584 pixels[j+3] = basepixels[j+3];
2586 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);
2591 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2592 //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]);
2594 // _norm is the name used by tenebrae and has been adopted as standard
2597 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2599 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);
2603 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2605 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2606 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2607 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);
2609 Mem_Free(bumppixels);
2611 else if (r_shadow_bumpscale_basetexture.value > 0)
2613 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2614 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2615 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);
2619 // _luma is supported for tenebrae compatibility
2620 // (I think it's a very stupid name, but oh well)
2621 // _glow is the preferred name
2622 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;}
2623 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;}
2624 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;}
2625 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;}
2628 Mem_Free(basepixels);
2633 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2635 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, NULL);
2638 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)
2643 for (i = 0;i < width*height;i++)
2644 if (((unsigned char *)&palette[in[i]])[3] > 0)
2646 if (i == width*height)
2649 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2652 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2653 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2656 unsigned char *temp1, *temp2;
2657 skinframe_t *skinframe;
2659 if (cls.state == ca_dedicated)
2662 // if already loaded just return it, otherwise make a new skinframe
2663 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2664 if (skinframe && skinframe->base)
2667 skinframe->stain = NULL;
2668 skinframe->merged = NULL;
2669 skinframe->base = r_texture_notexture;
2670 skinframe->pants = NULL;
2671 skinframe->shirt = NULL;
2672 skinframe->nmap = r_texture_blanknormalmap;
2673 skinframe->gloss = NULL;
2674 skinframe->glow = NULL;
2675 skinframe->fog = NULL;
2677 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2681 if (developer_loading.integer)
2682 Con_Printf("loading 32bit skin \"%s\"\n", name);
2684 if (r_shadow_bumpscale_basetexture.value > 0)
2686 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2687 temp2 = temp1 + width * height * 4;
2688 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2689 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2692 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2693 if (textureflags & TEXF_ALPHA)
2695 for (i = 3;i < width * height * 4;i += 4)
2696 if (skindata[i] < 255)
2698 if (i < width * height * 4)
2700 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2701 memcpy(fogpixels, skindata, width * height * 4);
2702 for (i = 0;i < width * height * 4;i += 4)
2703 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2704 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2705 Mem_Free(fogpixels);
2709 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2710 //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]);
2715 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2718 unsigned char *temp1, *temp2;
2719 unsigned int *palette;
2720 skinframe_t *skinframe;
2722 if (cls.state == ca_dedicated)
2725 // if already loaded just return it, otherwise make a new skinframe
2726 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2727 if (skinframe && skinframe->base)
2730 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2732 skinframe->stain = NULL;
2733 skinframe->merged = NULL;
2734 skinframe->base = r_texture_notexture;
2735 skinframe->pants = NULL;
2736 skinframe->shirt = NULL;
2737 skinframe->nmap = r_texture_blanknormalmap;
2738 skinframe->gloss = NULL;
2739 skinframe->glow = NULL;
2740 skinframe->fog = NULL;
2742 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2746 if (developer_loading.integer)
2747 Con_Printf("loading quake skin \"%s\"\n", name);
2749 if (r_shadow_bumpscale_basetexture.value > 0)
2751 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2752 temp2 = temp1 + width * height * 4;
2753 // use either a custom palette or the quake palette
2754 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2755 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2756 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2759 // use either a custom palette, or the quake palette
2760 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2761 if (loadglowtexture)
2762 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2763 if (loadpantsandshirt)
2765 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2766 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2768 if (skinframe->pants || skinframe->shirt)
2769 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
2770 if (textureflags & TEXF_ALPHA)
2772 for (i = 0;i < width * height;i++)
2773 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2775 if (i < width * height)
2776 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2779 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2780 //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]);
2785 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)
2788 skinframe_t *skinframe;
2790 if (cls.state == ca_dedicated)
2793 // if already loaded just return it, otherwise make a new skinframe
2794 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2795 if (skinframe && skinframe->base)
2798 skinframe->stain = NULL;
2799 skinframe->merged = NULL;
2800 skinframe->base = r_texture_notexture;
2801 skinframe->pants = NULL;
2802 skinframe->shirt = NULL;
2803 skinframe->nmap = r_texture_blanknormalmap;
2804 skinframe->gloss = NULL;
2805 skinframe->glow = NULL;
2806 skinframe->fog = NULL;
2808 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2812 if (developer_loading.integer)
2813 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2815 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, skinframe->basename, palette, skinframe->textureflags, true);
2816 if (textureflags & TEXF_ALPHA)
2818 for (i = 0;i < width * height;i++)
2819 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
2821 if (i < width * height)
2822 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
2825 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2826 //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]);
2831 skinframe_t *R_SkinFrame_LoadMissing(void)
2833 skinframe_t *skinframe;
2835 if (cls.state == ca_dedicated)
2838 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2839 skinframe->stain = NULL;
2840 skinframe->merged = NULL;
2841 skinframe->base = r_texture_notexture;
2842 skinframe->pants = NULL;
2843 skinframe->shirt = NULL;
2844 skinframe->nmap = r_texture_blanknormalmap;
2845 skinframe->gloss = NULL;
2846 skinframe->glow = NULL;
2847 skinframe->fog = NULL;
2849 skinframe->avgcolor[0] = rand() / RAND_MAX;
2850 skinframe->avgcolor[1] = rand() / RAND_MAX;
2851 skinframe->avgcolor[2] = rand() / RAND_MAX;
2852 skinframe->avgcolor[3] = 1;
2857 void R_Main_FreeViewCache(void)
2859 if (r_refdef.viewcache.entityvisible)
2860 Mem_Free(r_refdef.viewcache.entityvisible);
2861 if (r_refdef.viewcache.world_pvsbits)
2862 Mem_Free(r_refdef.viewcache.world_pvsbits);
2863 if (r_refdef.viewcache.world_leafvisible)
2864 Mem_Free(r_refdef.viewcache.world_leafvisible);
2865 if (r_refdef.viewcache.world_surfacevisible)
2866 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2867 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2870 void R_Main_AllocViewCache(void)
2872 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2873 r_refdef.viewcache.maxentities = r_refdef.scene.maxentities;
2874 if (r_refdef.viewcache.maxentities)
2875 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
2878 r_refdef.viewcache.world_numclusters = cl.worldmodel->brush.num_pvsclusters;
2879 r_refdef.viewcache.world_numleafs = cl.worldmodel->brush.num_leafs;
2880 r_refdef.viewcache.world_numsurfaces = cl.worldmodel->num_surfaces;
2881 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, (r_refdef.viewcache.world_numclusters+7)>>3);
2882 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
2883 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
2887 void gl_main_start(void)
2889 R_Main_AllocViewCache();
2893 memset(r_queries, 0, sizeof(r_queries));
2895 r_qwskincache = NULL;
2896 r_qwskincache_size = 0;
2898 // set up r_skinframe loading system for textures
2899 memset(&r_skinframe, 0, sizeof(r_skinframe));
2900 r_skinframe.loadsequence = 1;
2901 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2903 r_main_texturepool = R_AllocTexturePool();
2904 R_BuildBlankTextures();
2906 if (gl_texturecubemap)
2909 R_BuildNormalizationCube();
2911 r_texture_fogattenuation = NULL;
2912 r_texture_gammaramps = NULL;
2913 //r_texture_fogintensity = NULL;
2914 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2915 memset(&r_waterstate, 0, sizeof(r_waterstate));
2916 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2917 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2918 memset(&r_svbsp, 0, sizeof (r_svbsp));
2920 r_refdef.fogmasktable_density = 0;
2923 extern rtexture_t *loadingscreentexture;
2924 void gl_main_shutdown(void)
2926 R_Main_FreeViewCache();
2929 qglDeleteQueriesARB(r_maxqueries, r_queries);
2933 memset(r_queries, 0, sizeof(r_queries));
2935 r_qwskincache = NULL;
2936 r_qwskincache_size = 0;
2938 // clear out the r_skinframe state
2939 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2940 memset(&r_skinframe, 0, sizeof(r_skinframe));
2943 Mem_Free(r_svbsp.nodes);
2944 memset(&r_svbsp, 0, sizeof (r_svbsp));
2945 R_FreeTexturePool(&r_main_texturepool);
2946 loadingscreentexture = NULL;
2947 r_texture_blanknormalmap = NULL;
2948 r_texture_white = NULL;
2949 r_texture_grey128 = NULL;
2950 r_texture_black = NULL;
2951 r_texture_whitecube = NULL;
2952 r_texture_normalizationcube = NULL;
2953 r_texture_fogattenuation = NULL;
2954 r_texture_gammaramps = NULL;
2955 //r_texture_fogintensity = NULL;
2956 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2957 memset(&r_waterstate, 0, sizeof(r_waterstate));
2961 extern void CL_ParseEntityLump(char *entitystring);
2962 void gl_main_newmap(void)
2964 // FIXME: move this code to client
2966 char *entities, entname[MAX_QPATH];
2968 Mem_Free(r_qwskincache);
2969 r_qwskincache = NULL;
2970 r_qwskincache_size = 0;
2973 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2974 l = (int)strlen(entname) - 4;
2975 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2977 memcpy(entname + l, ".ent", 5);
2978 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2980 CL_ParseEntityLump(entities);
2985 if (cl.worldmodel->brush.entities)
2986 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2988 R_Main_FreeViewCache();
2989 R_Main_AllocViewCache();
2992 void GL_Main_Init(void)
2994 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2996 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2997 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2998 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2999 if (gamemode == GAME_NEHAHRA)
3001 Cvar_RegisterVariable (&gl_fogenable);
3002 Cvar_RegisterVariable (&gl_fogdensity);
3003 Cvar_RegisterVariable (&gl_fogred);
3004 Cvar_RegisterVariable (&gl_foggreen);
3005 Cvar_RegisterVariable (&gl_fogblue);
3006 Cvar_RegisterVariable (&gl_fogstart);
3007 Cvar_RegisterVariable (&gl_fogend);
3008 Cvar_RegisterVariable (&gl_skyclip);
3010 Cvar_RegisterVariable(&r_motionblur);
3011 Cvar_RegisterVariable(&r_motionblur_maxblur);
3012 Cvar_RegisterVariable(&r_motionblur_bmin);
3013 Cvar_RegisterVariable(&r_motionblur_vmin);
3014 Cvar_RegisterVariable(&r_motionblur_vmax);
3015 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3016 Cvar_RegisterVariable(&r_motionblur_randomize);
3017 Cvar_RegisterVariable(&r_damageblur);
3018 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3019 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3020 Cvar_RegisterVariable(&r_equalize_entities_by);
3021 Cvar_RegisterVariable(&r_equalize_entities_to);
3022 Cvar_RegisterVariable(&r_animcache);
3023 Cvar_RegisterVariable(&r_depthfirst);
3024 Cvar_RegisterVariable(&r_useinfinitefarclip);
3025 Cvar_RegisterVariable(&r_farclip_base);
3026 Cvar_RegisterVariable(&r_farclip_world);
3027 Cvar_RegisterVariable(&r_nearclip);
3028 Cvar_RegisterVariable(&r_showbboxes);
3029 Cvar_RegisterVariable(&r_showsurfaces);
3030 Cvar_RegisterVariable(&r_showtris);
3031 Cvar_RegisterVariable(&r_shownormals);
3032 Cvar_RegisterVariable(&r_showlighting);
3033 Cvar_RegisterVariable(&r_showshadowvolumes);
3034 Cvar_RegisterVariable(&r_showcollisionbrushes);
3035 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3036 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3037 Cvar_RegisterVariable(&r_showdisabledepthtest);
3038 Cvar_RegisterVariable(&r_drawportals);
3039 Cvar_RegisterVariable(&r_drawentities);
3040 Cvar_RegisterVariable(&r_cullentities_trace);
3041 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3042 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3043 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3044 Cvar_RegisterVariable(&r_drawviewmodel);
3045 Cvar_RegisterVariable(&r_speeds);
3046 Cvar_RegisterVariable(&r_fullbrights);
3047 Cvar_RegisterVariable(&r_wateralpha);
3048 Cvar_RegisterVariable(&r_dynamic);
3049 Cvar_RegisterVariable(&r_fullbright);
3050 Cvar_RegisterVariable(&r_shadows);
3051 Cvar_RegisterVariable(&r_shadows_darken);
3052 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3053 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3054 Cvar_RegisterVariable(&r_shadows_throwdistance);
3055 Cvar_RegisterVariable(&r_shadows_throwdirection);
3056 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3057 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3058 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3059 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3060 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3061 Cvar_RegisterVariable(&r_fog_exp2);
3062 Cvar_RegisterVariable(&r_drawfog);
3063 Cvar_RegisterVariable(&r_textureunits);
3064 Cvar_RegisterVariable(&r_glsl);
3065 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3066 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3067 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3068 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3069 Cvar_RegisterVariable(&r_glsl_postprocess);
3070 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3071 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3072 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3073 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3074 Cvar_RegisterVariable(&r_glsl_usegeneric);
3075 Cvar_RegisterVariable(&r_water);
3076 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3077 Cvar_RegisterVariable(&r_water_clippingplanebias);
3078 Cvar_RegisterVariable(&r_water_refractdistort);
3079 Cvar_RegisterVariable(&r_water_reflectdistort);
3080 Cvar_RegisterVariable(&r_lerpsprites);
3081 Cvar_RegisterVariable(&r_lerpmodels);
3082 Cvar_RegisterVariable(&r_lerplightstyles);
3083 Cvar_RegisterVariable(&r_waterscroll);
3084 Cvar_RegisterVariable(&r_bloom);
3085 Cvar_RegisterVariable(&r_bloom_colorscale);
3086 Cvar_RegisterVariable(&r_bloom_brighten);
3087 Cvar_RegisterVariable(&r_bloom_blur);
3088 Cvar_RegisterVariable(&r_bloom_resolution);
3089 Cvar_RegisterVariable(&r_bloom_colorexponent);
3090 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3091 Cvar_RegisterVariable(&r_hdr);
3092 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3093 Cvar_RegisterVariable(&r_hdr_glowintensity);
3094 Cvar_RegisterVariable(&r_hdr_range);
3095 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3096 Cvar_RegisterVariable(&developer_texturelogging);
3097 Cvar_RegisterVariable(&gl_lightmaps);
3098 Cvar_RegisterVariable(&r_test);
3099 Cvar_RegisterVariable(&r_batchmode);
3100 Cvar_RegisterVariable(&r_glsl_saturation);
3101 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3102 Cvar_SetValue("r_fullbrights", 0);
3103 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3105 Cvar_RegisterVariable(&r_track_sprites);
3106 Cvar_RegisterVariable(&r_track_sprites_flags);
3107 Cvar_RegisterVariable(&r_track_sprites_scalew);
3108 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3111 extern void R_Textures_Init(void);
3112 extern void GL_Draw_Init(void);
3113 extern void GL_Main_Init(void);
3114 extern void R_Shadow_Init(void);
3115 extern void R_Sky_Init(void);
3116 extern void GL_Surf_Init(void);
3117 extern void R_Particles_Init(void);
3118 extern void R_Explosion_Init(void);
3119 extern void gl_backend_init(void);
3120 extern void Sbar_Init(void);
3121 extern void R_LightningBeams_Init(void);
3122 extern void Mod_RenderInit(void);
3124 void Render_Init(void)
3136 R_LightningBeams_Init();
3145 extern char *ENGINE_EXTENSIONS;
3148 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3149 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3150 gl_version = (const char *)qglGetString(GL_VERSION);
3151 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3155 if (!gl_platformextensions)
3156 gl_platformextensions = "";
3158 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3159 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3160 Con_Printf("GL_VERSION: %s\n", gl_version);
3161 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3162 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3164 VID_CheckExtensions();
3166 // LordHavoc: report supported extensions
3167 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3169 // clear to black (loading plaque will be seen over this)
3171 qglClearColor(0,0,0,1);CHECKGLERROR
3172 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3175 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3179 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3181 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3184 p = r_refdef.view.frustum + i;
3189 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3193 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3197 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3201 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3205 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3209 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3213 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3217 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3225 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3229 for (i = 0;i < numplanes;i++)
3236 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3240 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3244 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3248 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3252 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3256 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3260 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3264 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3272 //==================================================================================
3274 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3277 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3278 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3279 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3282 typedef struct r_animcache_entity_s
3289 qboolean wantnormals;
3290 qboolean wanttangents;
3292 r_animcache_entity_t;
3294 typedef struct r_animcache_s
3296 r_animcache_entity_t entity[MAX_EDICTS];
3302 static r_animcache_t r_animcachestate;
3304 void R_AnimCache_Free(void)
3307 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3309 r_animcachestate.entity[idx].maxvertices = 0;
3310 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3311 r_animcachestate.entity[idx].vertex3f = NULL;
3312 r_animcachestate.entity[idx].normal3f = NULL;
3313 r_animcachestate.entity[idx].svector3f = NULL;
3314 r_animcachestate.entity[idx].tvector3f = NULL;
3316 r_animcachestate.currentindex = 0;
3317 r_animcachestate.maxindex = 0;
3320 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3324 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3326 if (cache->maxvertices >= numvertices)
3329 // Release existing memory
3330 if (cache->vertex3f)
3331 Mem_Free(cache->vertex3f);
3333 // Pad by 1024 verts
3334 cache->maxvertices = (numvertices + 1023) & ~1023;
3335 arraySize = cache->maxvertices * 3;
3337 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3338 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3339 r_animcachestate.entity[cacheIdx].vertex3f = base;
3340 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3341 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3342 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3344 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3347 void R_AnimCache_NewFrame(void)
3351 if (r_animcache.integer && r_drawentities.integer)
3352 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3353 else if (r_animcachestate.maxindex)
3356 r_animcachestate.currentindex = 0;
3358 for (i = 0;i < r_refdef.scene.numentities;i++)
3359 r_refdef.scene.entities[i]->animcacheindex = -1;
3362 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3364 dp_model_t *model = ent->model;
3365 r_animcache_entity_t *c;
3366 // see if it's already cached this frame
3367 if (ent->animcacheindex >= 0)
3369 // add normals/tangents if needed
3370 c = r_animcachestate.entity + ent->animcacheindex;
3372 wantnormals = false;
3373 if (c->wanttangents)
3374 wanttangents = false;
3375 if (wantnormals || wanttangents)
3376 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3380 // see if this ent is worth caching
3381 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3383 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3385 // assign it a cache entry and make sure the arrays are big enough
3386 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3387 ent->animcacheindex = r_animcachestate.currentindex++;
3388 c = r_animcachestate.entity + ent->animcacheindex;
3389 c->wantnormals = wantnormals;
3390 c->wanttangents = wanttangents;
3391 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3396 void R_AnimCache_CacheVisibleEntities(void)
3399 qboolean wantnormals;
3400 qboolean wanttangents;
3402 if (!r_animcachestate.maxindex)
3405 wantnormals = !r_showsurfaces.integer;
3406 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3408 // TODO: thread this?
3410 for (i = 0;i < r_refdef.scene.numentities;i++)
3412 if (!r_refdef.viewcache.entityvisible[i])
3414 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3418 //==================================================================================
3420 static void R_View_UpdateEntityLighting (void)
3423 entity_render_t *ent;
3424 vec3_t tempdiffusenormal, avg;
3425 vec_t f, fa, fd, fdd;
3427 for (i = 0;i < r_refdef.scene.numentities;i++)
3429 ent = r_refdef.scene.entities[i];
3431 // skip unseen models
3432 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3436 if (ent->model && ent->model->brush.num_leafs)
3438 // TODO: use modellight for r_ambient settings on world?
3439 VectorSet(ent->modellight_ambient, 0, 0, 0);
3440 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3441 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3445 // fetch the lighting from the worldmodel data
3446 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));
3447 VectorClear(ent->modellight_diffuse);
3448 VectorClear(tempdiffusenormal);
3449 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3452 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3453 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3454 if(ent->flags & RENDER_EQUALIZE)
3456 // first fix up ambient lighting...
3457 if(r_equalize_entities_minambient.value > 0)
3459 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3462 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3463 if(fa < r_equalize_entities_minambient.value * fd)
3466 // fa'/fd' = minambient
3467 // fa'+0.25*fd' = fa+0.25*fd
3469 // fa' = fd' * minambient
3470 // fd'*(0.25+minambient) = fa+0.25*fd
3472 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3473 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3475 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3476 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
3477 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3478 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3483 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3485 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3486 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3489 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3490 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3491 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3497 VectorSet(ent->modellight_ambient, 1, 1, 1);
3499 // move the light direction into modelspace coordinates for lighting code
3500 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3501 if(VectorLength2(ent->modellight_lightdir) == 0)
3502 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3503 VectorNormalize(ent->modellight_lightdir);
3507 #define MAX_LINEOFSIGHTTRACES 64
3509 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3512 vec3_t boxmins, boxmaxs;
3515 dp_model_t *model = r_refdef.scene.worldmodel;
3517 if (!model || !model->brush.TraceLineOfSight)
3520 // expand the box a little
3521 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3522 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3523 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3524 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3525 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3526 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3529 VectorCopy(eye, start);
3530 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3531 if (model->brush.TraceLineOfSight(model, start, end))
3534 // try various random positions
3535 for (i = 0;i < numsamples;i++)
3537 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3538 if (model->brush.TraceLineOfSight(model, start, end))
3546 static void R_View_UpdateEntityVisible (void)
3549 entity_render_t *ent;
3551 if (!r_drawentities.integer)
3554 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3555 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3557 // worldmodel can check visibility
3558 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3559 for (i = 0;i < r_refdef.scene.numentities;i++)
3561 ent = r_refdef.scene.entities[i];
3562 if (!(ent->flags & renderimask))
3563 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)))
3564 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))
3565 r_refdef.viewcache.entityvisible[i] = true;
3567 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3569 for (i = 0;i < r_refdef.scene.numentities;i++)
3571 ent = r_refdef.scene.entities[i];
3572 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3574 if(R_CanSeeBox(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3575 ent->last_trace_visibility = realtime;
3576 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3577 r_refdef.viewcache.entityvisible[i] = 0;
3584 // no worldmodel or it can't check visibility
3585 for (i = 0;i < r_refdef.scene.numentities;i++)
3587 ent = r_refdef.scene.entities[i];
3588 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));
3593 /// only used if skyrendermasked, and normally returns false
3594 int R_DrawBrushModelsSky (void)
3597 entity_render_t *ent;
3599 if (!r_drawentities.integer)
3603 for (i = 0;i < r_refdef.scene.numentities;i++)
3605 if (!r_refdef.viewcache.entityvisible[i])
3607 ent = r_refdef.scene.entities[i];
3608 if (!ent->model || !ent->model->DrawSky)
3610 ent->model->DrawSky(ent);
3616 static void R_DrawNoModel(entity_render_t *ent);
3617 static void R_DrawModels(void)
3620 entity_render_t *ent;
3622 if (!r_drawentities.integer)
3625 for (i = 0;i < r_refdef.scene.numentities;i++)
3627 if (!r_refdef.viewcache.entityvisible[i])
3629 ent = r_refdef.scene.entities[i];
3630 r_refdef.stats.entities++;
3631 if (ent->model && ent->model->Draw != NULL)
3632 ent->model->Draw(ent);
3638 static void R_DrawModelsDepth(void)
3641 entity_render_t *ent;
3643 if (!r_drawentities.integer)
3646 for (i = 0;i < r_refdef.scene.numentities;i++)
3648 if (!r_refdef.viewcache.entityvisible[i])
3650 ent = r_refdef.scene.entities[i];
3651 if (ent->model && ent->model->DrawDepth != NULL)
3652 ent->model->DrawDepth(ent);
3656 static void R_DrawModelsDebug(void)
3659 entity_render_t *ent;
3661 if (!r_drawentities.integer)
3664 for (i = 0;i < r_refdef.scene.numentities;i++)
3666 if (!r_refdef.viewcache.entityvisible[i])
3668 ent = r_refdef.scene.entities[i];
3669 if (ent->model && ent->model->DrawDebug != NULL)
3670 ent->model->DrawDebug(ent);
3674 static void R_DrawModelsAddWaterPlanes(void)
3677 entity_render_t *ent;
3679 if (!r_drawentities.integer)
3682 for (i = 0;i < r_refdef.scene.numentities;i++)
3684 if (!r_refdef.viewcache.entityvisible[i])
3686 ent = r_refdef.scene.entities[i];
3687 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3688 ent->model->DrawAddWaterPlanes(ent);
3692 static void R_DrawModelDecals_Entity(entity_render_t *ent);
3693 static void R_DrawModelDecals(void)
3696 entity_render_t *ent;
3698 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
3700 if (!r_drawentities.integer || r_showsurfaces.integer)
3703 for (i = 0;i < r_refdef.scene.numentities;i++)
3705 if (!r_refdef.viewcache.entityvisible[i])
3707 ent = r_refdef.scene.entities[i];
3708 r_refdef.stats.entities++;
3709 if (ent->decalsystem.numdecals)
3710 R_DrawModelDecals_Entity(ent);
3714 static void R_View_SetFrustum(void)
3717 double slopex, slopey;
3718 vec3_t forward, left, up, origin;
3720 // we can't trust r_refdef.view.forward and friends in reflected scenes
3721 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3724 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3725 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3726 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3727 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3728 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3729 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3730 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3731 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3732 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3733 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3734 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3735 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3739 zNear = r_refdef.nearclip;
3740 nudge = 1.0 - 1.0 / (1<<23);
3741 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3742 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3743 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3744 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3745 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3746 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3747 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3748 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3754 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3755 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3756 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3757 r_refdef.view.frustum[0].dist = m[15] - m[12];
3759 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3760 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3761 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3762 r_refdef.view.frustum[1].dist = m[15] + m[12];
3764 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3765 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3766 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3767 r_refdef.view.frustum[2].dist = m[15] - m[13];
3769 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3770 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3771 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3772 r_refdef.view.frustum[3].dist = m[15] + m[13];
3774 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3775 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3776 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3777 r_refdef.view.frustum[4].dist = m[15] - m[14];
3779 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3780 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3781 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3782 r_refdef.view.frustum[5].dist = m[15] + m[14];
3785 if (r_refdef.view.useperspective)
3787 slopex = 1.0 / r_refdef.view.frustum_x;
3788 slopey = 1.0 / r_refdef.view.frustum_y;
3789 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3790 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3791 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3792 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3793 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3795 // Leaving those out was a mistake, those were in the old code, and they
3796 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3797 // I couldn't reproduce it after adding those normalizations. --blub
3798 VectorNormalize(r_refdef.view.frustum[0].normal);
3799 VectorNormalize(r_refdef.view.frustum[1].normal);
3800 VectorNormalize(r_refdef.view.frustum[2].normal);
3801 VectorNormalize(r_refdef.view.frustum[3].normal);
3803 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3804 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]);
3805 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]);
3806 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]);
3807 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, 1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
3809 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3810 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3811 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3812 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3813 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3817 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3818 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3819 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3820 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3821 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3822 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3823 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3824 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3825 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3826 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3828 r_refdef.view.numfrustumplanes = 5;
3830 if (r_refdef.view.useclipplane)
3832 r_refdef.view.numfrustumplanes = 6;
3833 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3836 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3837 PlaneClassify(r_refdef.view.frustum + i);
3839 // LordHavoc: note to all quake engine coders, Quake had a special case
3840 // for 90 degrees which assumed a square view (wrong), so I removed it,
3841 // Quake2 has it disabled as well.
3843 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3844 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3845 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3846 //PlaneClassify(&frustum[0]);
3848 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3849 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3850 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3851 //PlaneClassify(&frustum[1]);
3853 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3854 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3855 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3856 //PlaneClassify(&frustum[2]);
3858 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3859 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3860 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3861 //PlaneClassify(&frustum[3]);
3864 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3865 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3866 //PlaneClassify(&frustum[4]);
3869 void R_View_Update(void)
3871 R_View_SetFrustum();
3872 R_View_WorldVisibility(r_refdef.view.useclipplane);
3873 R_View_UpdateEntityVisible();
3874 R_View_UpdateEntityLighting();
3877 void R_SetupView(qboolean allowwaterclippingplane)
3879 const double *customclipplane = NULL;
3881 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3883 // LordHavoc: couldn't figure out how to make this approach the
3884 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3885 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3886 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3887 dist = r_refdef.view.clipplane.dist;
3888 plane[0] = r_refdef.view.clipplane.normal[0];
3889 plane[1] = r_refdef.view.clipplane.normal[1];
3890 plane[2] = r_refdef.view.clipplane.normal[2];
3892 customclipplane = plane;
3895 if (!r_refdef.view.useperspective)
3896 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);
3897 else if (gl_stencil && r_useinfinitefarclip.integer)
3898 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);
3900 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);
3901 R_SetViewport(&r_refdef.view.viewport);
3904 void R_ResetViewRendering2D(void)
3906 r_viewport_t viewport;
3909 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3910 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);
3911 R_SetViewport(&viewport);
3912 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3913 GL_Color(1, 1, 1, 1);
3914 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3915 GL_BlendFunc(GL_ONE, GL_ZERO);
3916 GL_AlphaTest(false);
3917 GL_ScissorTest(false);
3918 GL_DepthMask(false);
3919 GL_DepthRange(0, 1);
3920 GL_DepthTest(false);
3921 R_Mesh_Matrix(&identitymatrix);
3922 R_Mesh_ResetTextureState();
3923 GL_PolygonOffset(0, 0);
3924 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3925 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3926 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3927 qglStencilMask(~0);CHECKGLERROR
3928 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3929 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3930 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3931 R_SetupGenericShader(true);
3934 void R_ResetViewRendering3D(void)
3939 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3940 GL_Color(1, 1, 1, 1);
3941 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3942 GL_BlendFunc(GL_ONE, GL_ZERO);
3943 GL_AlphaTest(false);
3944 GL_ScissorTest(true);
3946 GL_DepthRange(0, 1);
3948 R_Mesh_Matrix(&identitymatrix);
3949 R_Mesh_ResetTextureState();
3950 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3951 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3952 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3953 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3954 qglStencilMask(~0);CHECKGLERROR
3955 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3956 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3957 GL_CullFace(r_refdef.view.cullface_back);
3958 R_SetupGenericShader(true);
3961 void R_RenderScene(void);
3962 void R_RenderWaterPlanes(void);
3964 static void R_Water_StartFrame(void)
3967 int waterwidth, waterheight, texturewidth, textureheight;
3968 r_waterstate_waterplane_t *p;
3970 // set waterwidth and waterheight to the water resolution that will be
3971 // used (often less than the screen resolution for faster rendering)
3972 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3973 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3975 // calculate desired texture sizes
3976 // can't use water if the card does not support the texture size
3977 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3978 texturewidth = textureheight = waterwidth = waterheight = 0;
3979 else if (gl_support_arb_texture_non_power_of_two)
3981 texturewidth = waterwidth;
3982 textureheight = waterheight;
3986 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3987 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3990 // allocate textures as needed
3991 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3993 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3994 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3996 if (p->texture_refraction)
3997 R_FreeTexture(p->texture_refraction);
3998 p->texture_refraction = NULL;
3999 if (p->texture_reflection)
4000 R_FreeTexture(p->texture_reflection);
4001 p->texture_reflection = NULL;
4003 memset(&r_waterstate, 0, sizeof(r_waterstate));
4004 r_waterstate.texturewidth = texturewidth;
4005 r_waterstate.textureheight = textureheight;
4008 if (r_waterstate.texturewidth)
4010 r_waterstate.enabled = true;
4012 // when doing a reduced render (HDR) we want to use a smaller area
4013 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4014 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4016 // set up variables that will be used in shader setup
4017 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4018 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4019 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4020 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4023 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4024 r_waterstate.numwaterplanes = 0;
4027 void R_Water_AddWaterPlane(msurface_t *surface)
4029 int triangleindex, planeindex;
4035 r_waterstate_waterplane_t *p;
4036 texture_t *t = R_GetCurrentTexture(surface->texture);
4037 // just use the first triangle with a valid normal for any decisions
4038 VectorClear(normal);
4039 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4041 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4042 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4043 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4044 TriangleNormal(vert[0], vert[1], vert[2], normal);
4045 if (VectorLength2(normal) >= 0.001)
4049 VectorCopy(normal, plane.normal);
4050 VectorNormalize(plane.normal);
4051 plane.dist = DotProduct(vert[0], plane.normal);
4052 PlaneClassify(&plane);
4053 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4055 // skip backfaces (except if nocullface is set)
4056 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4058 VectorNegate(plane.normal, plane.normal);
4060 PlaneClassify(&plane);
4064 // find a matching plane if there is one
4065 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4066 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4068 if (planeindex >= r_waterstate.maxwaterplanes)
4069 return; // nothing we can do, out of planes
4071 // if this triangle does not fit any known plane rendered this frame, add one
4072 if (planeindex >= r_waterstate.numwaterplanes)
4074 // store the new plane
4075 r_waterstate.numwaterplanes++;
4077 // clear materialflags and pvs
4078 p->materialflags = 0;
4079 p->pvsvalid = false;
4081 // merge this surface's materialflags into the waterplane
4082 p->materialflags |= t->currentmaterialflags;
4083 // merge this surface's PVS into the waterplane
4084 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4085 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4086 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4088 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4093 static void R_Water_ProcessPlanes(void)
4095 r_refdef_view_t originalview;
4096 r_refdef_view_t myview;
4098 r_waterstate_waterplane_t *p;
4100 originalview = r_refdef.view;
4102 // make sure enough textures are allocated
4103 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4105 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4107 if (!p->texture_refraction)
4108 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);
4109 if (!p->texture_refraction)
4113 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4115 if (!p->texture_reflection)
4116 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);
4117 if (!p->texture_reflection)
4123 r_refdef.view = originalview;
4124 r_refdef.view.showdebug = false;
4125 r_refdef.view.width = r_waterstate.waterwidth;
4126 r_refdef.view.height = r_waterstate.waterheight;
4127 r_refdef.view.useclipplane = true;
4128 myview = r_refdef.view;
4129 r_waterstate.renderingscene = true;
4130 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4132 // render the normal view scene and copy into texture
4133 // (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)
4134 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4136 r_refdef.view = myview;
4137 r_refdef.view.clipplane = p->plane;
4138 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4139 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4140 PlaneClassify(&r_refdef.view.clipplane);
4142 R_ResetViewRendering3D();
4143 R_ClearScreen(r_refdef.fogenabled);
4147 // copy view into the screen texture
4148 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4149 GL_ActiveTexture(0);
4151 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
4154 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4156 r_refdef.view = myview;
4157 // render reflected scene and copy into texture
4158 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4159 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4160 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4161 r_refdef.view.clipplane = p->plane;
4162 // reverse the cullface settings for this render
4163 r_refdef.view.cullface_front = GL_FRONT;
4164 r_refdef.view.cullface_back = GL_BACK;
4165 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4167 r_refdef.view.usecustompvs = true;
4169 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4171 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4174 R_ResetViewRendering3D();
4175 R_ClearScreen(r_refdef.fogenabled);
4179 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4180 GL_ActiveTexture(0);
4182 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
4185 r_waterstate.renderingscene = false;
4186 r_refdef.view = originalview;
4187 R_ResetViewRendering3D();
4188 R_ClearScreen(r_refdef.fogenabled);
4192 r_refdef.view = originalview;
4193 r_waterstate.renderingscene = false;
4194 Cvar_SetValueQuick(&r_water, 0);
4195 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4199 void R_Bloom_StartFrame(void)
4201 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4203 // set bloomwidth and bloomheight to the bloom resolution that will be
4204 // used (often less than the screen resolution for faster rendering)
4205 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4206 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4207 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4208 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
4209 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
4211 // calculate desired texture sizes
4212 if (gl_support_arb_texture_non_power_of_two)
4214 screentexturewidth = r_refdef.view.width;
4215 screentextureheight = r_refdef.view.height;
4216 bloomtexturewidth = r_bloomstate.bloomwidth;
4217 bloomtextureheight = r_bloomstate.bloomheight;
4221 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4222 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4223 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4224 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4227 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))
4229 Cvar_SetValueQuick(&r_hdr, 0);
4230 Cvar_SetValueQuick(&r_bloom, 0);
4231 Cvar_SetValueQuick(&r_motionblur, 0);
4232 Cvar_SetValueQuick(&r_damageblur, 0);
4235 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)))
4236 screentexturewidth = screentextureheight = 0;
4237 if (!r_hdr.integer && !r_bloom.integer)
4238 bloomtexturewidth = bloomtextureheight = 0;
4240 // allocate textures as needed
4241 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4243 if (r_bloomstate.texture_screen)
4244 R_FreeTexture(r_bloomstate.texture_screen);
4245 r_bloomstate.texture_screen = NULL;
4246 r_bloomstate.screentexturewidth = screentexturewidth;
4247 r_bloomstate.screentextureheight = screentextureheight;
4248 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4249 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);
4251 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4253 if (r_bloomstate.texture_bloom)
4254 R_FreeTexture(r_bloomstate.texture_bloom);
4255 r_bloomstate.texture_bloom = NULL;
4256 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4257 r_bloomstate.bloomtextureheight = bloomtextureheight;
4258 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4259 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);
4262 // when doing a reduced render (HDR) we want to use a smaller area
4263 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4264 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4265 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4266 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4267 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4269 // set up a texcoord array for the full resolution screen image
4270 // (we have to keep this around to copy back during final render)
4271 r_bloomstate.screentexcoord2f[0] = 0;
4272 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4273 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4274 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4275 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4276 r_bloomstate.screentexcoord2f[5] = 0;
4277 r_bloomstate.screentexcoord2f[6] = 0;
4278 r_bloomstate.screentexcoord2f[7] = 0;
4280 // set up a texcoord array for the reduced resolution bloom image
4281 // (which will be additive blended over the screen image)
4282 r_bloomstate.bloomtexcoord2f[0] = 0;
4283 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4284 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4285 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4286 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4287 r_bloomstate.bloomtexcoord2f[5] = 0;
4288 r_bloomstate.bloomtexcoord2f[6] = 0;
4289 r_bloomstate.bloomtexcoord2f[7] = 0;
4291 if (r_hdr.integer || r_bloom.integer)
4293 r_bloomstate.enabled = true;
4294 r_bloomstate.hdr = r_hdr.integer != 0;
4297 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);
4300 void R_Bloom_CopyBloomTexture(float colorscale)
4302 r_refdef.stats.bloom++;
4304 // scale down screen texture to the bloom texture size
4306 R_SetViewport(&r_bloomstate.viewport);
4307 GL_BlendFunc(GL_ONE, GL_ZERO);
4308 GL_Color(colorscale, colorscale, colorscale, 1);
4309 // TODO: optimize with multitexture or GLSL
4310 R_SetupGenericShader(true);
4311 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4312 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4313 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4314 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4316 // we now have a bloom image in the framebuffer
4317 // copy it into the bloom image texture for later processing
4318 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4319 GL_ActiveTexture(0);
4321 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4322 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4325 void R_Bloom_CopyHDRTexture(void)
4327 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4328 GL_ActiveTexture(0);
4330 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
4331 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4334 void R_Bloom_MakeTexture(void)
4337 float xoffset, yoffset, r, brighten;
4339 r_refdef.stats.bloom++;
4341 R_ResetViewRendering2D();
4342 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4343 R_Mesh_ColorPointer(NULL, 0, 0);
4344 R_SetupGenericShader(true);
4346 // we have a bloom image in the framebuffer
4348 R_SetViewport(&r_bloomstate.viewport);
4350 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4353 r = bound(0, r_bloom_colorexponent.value / x, 1);
4354 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4355 GL_Color(r, r, r, 1);
4356 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4357 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4358 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4359 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4361 // copy the vertically blurred bloom view to a texture
4362 GL_ActiveTexture(0);
4364 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4365 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4368 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4369 brighten = r_bloom_brighten.value;
4371 brighten *= r_hdr_range.value;
4372 brighten = sqrt(brighten);
4374 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4375 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4376 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4378 for (dir = 0;dir < 2;dir++)
4380 // blend on at multiple vertical offsets to achieve a vertical blur
4381 // TODO: do offset blends using GLSL
4382 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4383 GL_BlendFunc(GL_ONE, GL_ZERO);
4384 for (x = -range;x <= range;x++)
4386 if (!dir){xoffset = 0;yoffset = x;}
4387 else {xoffset = x;yoffset = 0;}
4388 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4389 yoffset /= (float)r_bloomstate.bloomtextureheight;
4390 // compute a texcoord array with the specified x and y offset
4391 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4392 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4393 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4394 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4395 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4396 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4397 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4398 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4399 // this r value looks like a 'dot' particle, fading sharply to
4400 // black at the edges
4401 // (probably not realistic but looks good enough)
4402 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4403 //r = brighten/(range*2+1);
4404 r = brighten / (range * 2 + 1);
4406 r *= (1 - x*x/(float)(range*range));
4407 GL_Color(r, r, r, 1);
4408 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4409 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4410 GL_BlendFunc(GL_ONE, GL_ONE);
4413 // copy the vertically blurred bloom view to a texture
4414 GL_ActiveTexture(0);
4416 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4417 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4420 // apply subtract last
4421 // (just like it would be in a GLSL shader)
4422 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4424 GL_BlendFunc(GL_ONE, GL_ZERO);
4425 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4426 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4427 GL_Color(1, 1, 1, 1);
4428 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4429 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4431 GL_BlendFunc(GL_ONE, GL_ONE);
4432 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4433 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4434 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4435 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4436 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4437 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4438 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4440 // copy the darkened bloom view to a texture
4441 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4442 GL_ActiveTexture(0);
4444 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4445 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4449 void R_HDR_RenderBloomTexture(void)
4451 int oldwidth, oldheight;
4452 float oldcolorscale;
4454 oldcolorscale = r_refdef.view.colorscale;
4455 oldwidth = r_refdef.view.width;
4456 oldheight = r_refdef.view.height;
4457 r_refdef.view.width = r_bloomstate.bloomwidth;
4458 r_refdef.view.height = r_bloomstate.bloomheight;
4460 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4461 // TODO: add exposure compensation features
4462 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4464 r_refdef.view.showdebug = false;
4465 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4467 R_ResetViewRendering3D();
4469 R_ClearScreen(r_refdef.fogenabled);
4470 if (r_timereport_active)
4471 R_TimeReport("HDRclear");
4474 if (r_timereport_active)
4475 R_TimeReport("visibility");
4477 // only do secondary renders with HDR if r_hdr is 2 or higher
4478 r_waterstate.numwaterplanes = 0;
4479 if (r_waterstate.enabled && r_hdr.integer >= 2)
4480 R_RenderWaterPlanes();
4482 r_refdef.view.showdebug = true;
4484 r_waterstate.numwaterplanes = 0;
4486 R_ResetViewRendering2D();
4488 R_Bloom_CopyHDRTexture();
4489 R_Bloom_MakeTexture();
4491 // restore the view settings
4492 r_refdef.view.width = oldwidth;
4493 r_refdef.view.height = oldheight;
4494 r_refdef.view.colorscale = oldcolorscale;
4496 R_ResetViewRendering3D();
4498 R_ClearScreen(r_refdef.fogenabled);
4499 if (r_timereport_active)
4500 R_TimeReport("viewclear");
4503 static void R_BlendView(void)
4505 if (r_bloomstate.texture_screen)
4507 // make sure the buffer is available
4508 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4510 R_ResetViewRendering2D();
4511 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4512 R_Mesh_ColorPointer(NULL, 0, 0);
4513 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4514 GL_ActiveTexture(0);CHECKGLERROR
4516 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4518 // declare variables
4520 static float avgspeed;
4522 speed = VectorLength(cl.movement_velocity);
4524 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4525 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4527 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4528 speed = bound(0, speed, 1);
4529 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4531 // calculate values into a standard alpha
4532 cl.motionbluralpha = 1 - exp(-
4534 (r_motionblur.value * speed / 80)
4536 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4539 max(0.0001, cl.time - cl.oldtime) // fps independent
4542 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4543 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4545 if (cl.motionbluralpha > 0)
4547 R_SetupGenericShader(true);
4548 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4549 GL_Color(1, 1, 1, cl.motionbluralpha);
4550 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4551 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4552 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4553 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4557 // copy view into the screen texture
4558 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
4559 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4562 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4564 unsigned int permutation =
4565 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4566 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4567 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4568 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4569 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4571 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4573 // render simple bloom effect
4574 // copy the screen and shrink it and darken it for the bloom process
4575 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4576 // make the bloom texture
4577 R_Bloom_MakeTexture();
4580 R_ResetViewRendering2D();
4581 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4582 R_Mesh_ColorPointer(NULL, 0, 0);
4583 GL_Color(1, 1, 1, 1);
4584 GL_BlendFunc(GL_ONE, GL_ZERO);
4585 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4586 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4587 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4588 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4589 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4590 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4591 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4592 if (r_glsl_permutation->loc_TintColor >= 0)
4593 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4594 if (r_glsl_permutation->loc_ClientTime >= 0)
4595 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4596 if (r_glsl_permutation->loc_PixelSize >= 0)
4597 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4598 if (r_glsl_permutation->loc_UserVec1 >= 0)
4600 float a=0, b=0, c=0, d=0;
4601 #if _MSC_VER >= 1400
4602 #define sscanf sscanf_s
4604 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4605 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4607 if (r_glsl_permutation->loc_UserVec2 >= 0)
4609 float a=0, b=0, c=0, d=0;
4610 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4611 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4613 if (r_glsl_permutation->loc_UserVec3 >= 0)
4615 float a=0, b=0, c=0, d=0;
4616 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4617 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4619 if (r_glsl_permutation->loc_UserVec4 >= 0)
4621 float a=0, b=0, c=0, d=0;
4622 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4623 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4625 if (r_glsl_permutation->loc_Saturation >= 0)
4626 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4627 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4628 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4634 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4636 // render high dynamic range bloom effect
4637 // the bloom texture was made earlier this render, so we just need to
4638 // blend it onto the screen...
4639 R_ResetViewRendering2D();
4640 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4641 R_Mesh_ColorPointer(NULL, 0, 0);
4642 R_SetupGenericShader(true);
4643 GL_Color(1, 1, 1, 1);
4644 GL_BlendFunc(GL_ONE, GL_ONE);
4645 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4646 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4647 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4648 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4650 else if (r_bloomstate.texture_bloom)
4652 // render simple bloom effect
4653 // copy the screen and shrink it and darken it for the bloom process
4654 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4655 // make the bloom texture
4656 R_Bloom_MakeTexture();
4657 // put the original screen image back in place and blend the bloom
4659 R_ResetViewRendering2D();
4660 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4661 R_Mesh_ColorPointer(NULL, 0, 0);
4662 GL_Color(1, 1, 1, 1);
4663 GL_BlendFunc(GL_ONE, GL_ZERO);
4664 // do both in one pass if possible
4665 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4666 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4667 if (r_textureunits.integer >= 2 && gl_combine.integer)
4669 R_SetupGenericTwoTextureShader(GL_ADD);
4670 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4671 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4675 R_SetupGenericShader(true);
4676 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4677 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4678 // now blend on the bloom texture
4679 GL_BlendFunc(GL_ONE, GL_ONE);
4680 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4681 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4683 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4684 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4686 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4688 // apply a color tint to the whole view
4689 R_ResetViewRendering2D();
4690 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4691 R_Mesh_ColorPointer(NULL, 0, 0);
4692 R_SetupGenericShader(false);
4693 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4694 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4695 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4699 matrix4x4_t r_waterscrollmatrix;
4701 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4703 if (r_refdef.fog_density)
4705 r_refdef.fogcolor[0] = r_refdef.fog_red;
4706 r_refdef.fogcolor[1] = r_refdef.fog_green;
4707 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4709 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4710 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4711 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4712 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4716 VectorCopy(r_refdef.fogcolor, fogvec);
4717 // color.rgb *= ContrastBoost * SceneBrightness;
4718 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4719 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4720 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4721 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4726 void R_UpdateVariables(void)
4730 r_refdef.scene.ambient = r_ambient.value;
4732 r_refdef.farclip = r_farclip_base.value;
4733 if (r_refdef.scene.worldmodel)
4734 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
4735 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4737 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4738 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4739 r_refdef.polygonfactor = 0;
4740 r_refdef.polygonoffset = 0;
4741 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4742 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4744 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4745 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4746 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4747 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4748 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4749 if (r_showsurfaces.integer)
4751 r_refdef.scene.rtworld = false;
4752 r_refdef.scene.rtworldshadows = false;
4753 r_refdef.scene.rtdlight = false;
4754 r_refdef.scene.rtdlightshadows = false;
4755 r_refdef.lightmapintensity = 0;
4758 if (gamemode == GAME_NEHAHRA)
4760 if (gl_fogenable.integer)
4762 r_refdef.oldgl_fogenable = true;
4763 r_refdef.fog_density = gl_fogdensity.value;
4764 r_refdef.fog_red = gl_fogred.value;
4765 r_refdef.fog_green = gl_foggreen.value;
4766 r_refdef.fog_blue = gl_fogblue.value;
4767 r_refdef.fog_alpha = 1;
4768 r_refdef.fog_start = 0;
4769 r_refdef.fog_end = gl_skyclip.value;
4770 r_refdef.fog_height = 1<<30;
4771 r_refdef.fog_fadedepth = 128;
4773 else if (r_refdef.oldgl_fogenable)
4775 r_refdef.oldgl_fogenable = false;
4776 r_refdef.fog_density = 0;
4777 r_refdef.fog_red = 0;
4778 r_refdef.fog_green = 0;
4779 r_refdef.fog_blue = 0;
4780 r_refdef.fog_alpha = 0;
4781 r_refdef.fog_start = 0;
4782 r_refdef.fog_end = 0;
4783 r_refdef.fog_height = 1<<30;
4784 r_refdef.fog_fadedepth = 128;
4788 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4789 r_refdef.fog_start = max(0, r_refdef.fog_start);
4790 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4792 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4794 if (r_refdef.fog_density && r_drawfog.integer)
4796 r_refdef.fogenabled = true;
4797 // this is the point where the fog reaches 0.9986 alpha, which we
4798 // consider a good enough cutoff point for the texture
4799 // (0.9986 * 256 == 255.6)
4800 if (r_fog_exp2.integer)
4801 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4803 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4804 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4805 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4806 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4807 // fog color was already set
4808 // update the fog texture
4809 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)
4810 R_BuildFogTexture();
4813 r_refdef.fogenabled = false;
4815 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4817 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4819 // build GLSL gamma texture
4820 #define RAMPWIDTH 256
4821 unsigned short ramp[RAMPWIDTH * 3];
4822 unsigned char rampbgr[RAMPWIDTH][4];
4825 r_texture_gammaramps_serial = vid_gammatables_serial;
4827 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4828 for(i = 0; i < RAMPWIDTH; ++i)
4830 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4831 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4832 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4835 if (r_texture_gammaramps)
4837 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4841 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);
4847 // remove GLSL gamma texture
4851 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4852 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4858 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4859 if( scenetype != r_currentscenetype ) {
4860 // store the old scenetype
4861 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4862 r_currentscenetype = scenetype;
4863 // move in the new scene
4864 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4873 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4875 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4876 if( scenetype == r_currentscenetype ) {
4877 return &r_refdef.scene;
4879 return &r_scenes_store[ scenetype ];
4888 void R_RenderView(void)
4890 if (r_timereport_active)
4891 R_TimeReport("start");
4892 r_frame++; // used only by R_GetCurrentTexture
4893 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4895 R_AnimCache_NewFrame();
4897 if (r_refdef.view.isoverlay)
4899 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4900 GL_Clear( GL_DEPTH_BUFFER_BIT );
4901 R_TimeReport("depthclear");
4903 r_refdef.view.showdebug = false;
4905 r_waterstate.enabled = false;
4906 r_waterstate.numwaterplanes = 0;
4914 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4915 return; //Host_Error ("R_RenderView: NULL worldmodel");
4917 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4919 // break apart the view matrix into vectors for various purposes
4920 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4921 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4922 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4923 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4924 // make an inverted copy of the view matrix for tracking sprites
4925 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4927 R_Shadow_UpdateWorldLightSelection();
4929 R_Bloom_StartFrame();
4930 R_Water_StartFrame();
4933 if (r_timereport_active)
4934 R_TimeReport("viewsetup");
4936 R_ResetViewRendering3D();
4938 if (r_refdef.view.clear || r_refdef.fogenabled)
4940 R_ClearScreen(r_refdef.fogenabled);
4941 if (r_timereport_active)
4942 R_TimeReport("viewclear");
4944 r_refdef.view.clear = true;
4946 // this produces a bloom texture to be used in R_BlendView() later
4948 R_HDR_RenderBloomTexture();
4950 r_refdef.view.showdebug = true;
4953 if (r_timereport_active)
4954 R_TimeReport("visibility");
4956 r_waterstate.numwaterplanes = 0;
4957 if (r_waterstate.enabled)
4958 R_RenderWaterPlanes();
4961 r_waterstate.numwaterplanes = 0;
4964 if (r_timereport_active)
4965 R_TimeReport("blendview");
4967 GL_Scissor(0, 0, vid.width, vid.height);
4968 GL_ScissorTest(false);
4972 void R_RenderWaterPlanes(void)
4974 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4976 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4977 if (r_timereport_active)
4978 R_TimeReport("waterworld");
4981 // don't let sound skip if going slow
4982 if (r_refdef.scene.extraupdate)
4985 R_DrawModelsAddWaterPlanes();
4986 if (r_timereport_active)
4987 R_TimeReport("watermodels");
4989 if (r_waterstate.numwaterplanes)
4991 R_Water_ProcessPlanes();
4992 if (r_timereport_active)
4993 R_TimeReport("waterscenes");
4997 extern void R_DrawLightningBeams (void);
4998 extern void VM_CL_AddPolygonsToMeshQueue (void);
4999 extern void R_DrawPortals (void);
5000 extern cvar_t cl_locs_show;
5001 static void R_DrawLocs(void);
5002 static void R_DrawEntityBBoxes(void);
5003 extern cvar_t cl_decals_newsystem;
5004 void R_RenderScene(void)
5006 r_refdef.stats.renders++;
5010 // don't let sound skip if going slow
5011 if (r_refdef.scene.extraupdate)
5014 R_MeshQueue_BeginScene();
5018 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);
5020 if (cl.csqc_vidvars.drawworld)
5022 // don't let sound skip if going slow
5023 if (r_refdef.scene.extraupdate)
5026 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5028 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5029 if (r_timereport_active)
5030 R_TimeReport("worldsky");
5033 if (R_DrawBrushModelsSky() && r_timereport_active)
5034 R_TimeReport("bmodelsky");
5036 if (skyrendermasked && skyrenderlater)
5038 // we have to force off the water clipping plane while rendering sky
5045 R_AnimCache_CacheVisibleEntities();
5047 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5049 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5050 if (r_timereport_active)
5051 R_TimeReport("worlddepth");
5053 if (r_depthfirst.integer >= 2)
5055 R_DrawModelsDepth();
5056 if (r_timereport_active)
5057 R_TimeReport("modeldepth");
5060 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5062 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5063 if (r_timereport_active)
5064 R_TimeReport("world");
5067 // don't let sound skip if going slow
5068 if (r_refdef.scene.extraupdate)
5072 if (r_timereport_active)
5073 R_TimeReport("models");
5075 // don't let sound skip if going slow
5076 if (r_refdef.scene.extraupdate)
5079 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5081 R_DrawModelShadows();
5082 R_ResetViewRendering3D();
5083 // don't let sound skip if going slow
5084 if (r_refdef.scene.extraupdate)
5088 R_ShadowVolumeLighting(false);
5089 if (r_timereport_active)
5090 R_TimeReport("rtlights");
5092 // don't let sound skip if going slow
5093 if (r_refdef.scene.extraupdate)
5096 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5098 R_DrawModelShadows();
5099 R_ResetViewRendering3D();
5100 // don't let sound skip if going slow
5101 if (r_refdef.scene.extraupdate)
5105 if (cl.csqc_vidvars.drawworld)
5107 if (cl_decals_newsystem.integer)
5109 R_DrawModelDecals();
5110 if (r_timereport_active)
5111 R_TimeReport("modeldecals");
5116 if (r_timereport_active)
5117 R_TimeReport("decals");
5121 if (r_timereport_active)
5122 R_TimeReport("particles");
5125 if (r_timereport_active)
5126 R_TimeReport("explosions");
5128 R_DrawLightningBeams();
5129 if (r_timereport_active)
5130 R_TimeReport("lightning");
5133 R_SetupGenericShader(true);
5134 VM_CL_AddPolygonsToMeshQueue();
5136 if (r_refdef.view.showdebug)
5138 if (cl_locs_show.integer)
5141 if (r_timereport_active)
5142 R_TimeReport("showlocs");
5145 if (r_drawportals.integer)
5148 if (r_timereport_active)
5149 R_TimeReport("portals");
5152 if (r_showbboxes.value > 0)
5154 R_DrawEntityBBoxes();
5155 if (r_timereport_active)
5156 R_TimeReport("bboxes");
5160 R_SetupGenericShader(true);
5161 R_MeshQueue_RenderTransparent();
5162 if (r_timereport_active)
5163 R_TimeReport("drawtrans");
5165 R_SetupGenericShader(true);
5167 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))
5169 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5170 if (r_timereport_active)
5171 R_TimeReport("worlddebug");
5172 R_DrawModelsDebug();
5173 if (r_timereport_active)
5174 R_TimeReport("modeldebug");
5177 R_SetupGenericShader(true);
5179 if (cl.csqc_vidvars.drawworld)
5182 if (r_timereport_active)
5183 R_TimeReport("coronas");
5186 // don't let sound skip if going slow
5187 if (r_refdef.scene.extraupdate)
5190 R_ResetViewRendering2D();
5193 static const unsigned short bboxelements[36] =
5203 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5206 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5208 RSurf_ActiveWorldEntity();
5210 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5211 GL_DepthMask(false);
5212 GL_DepthRange(0, 1);
5213 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5214 R_Mesh_ResetTextureState();
5216 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5217 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5218 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5219 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5220 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5221 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5222 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5223 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5224 R_FillColors(color4f, 8, cr, cg, cb, ca);
5225 if (r_refdef.fogenabled)
5227 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5229 f1 = RSurf_FogVertex(v);
5231 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5232 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5233 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5236 R_Mesh_VertexPointer(vertex3f, 0, 0);
5237 R_Mesh_ColorPointer(color4f, 0, 0);
5238 R_Mesh_ResetTextureState();
5239 R_SetupGenericShader(false);
5240 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5243 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5247 prvm_edict_t *edict;
5248 prvm_prog_t *prog_save = prog;
5250 // this function draws bounding boxes of server entities
5254 GL_CullFace(GL_NONE);
5255 R_SetupGenericShader(false);
5259 for (i = 0;i < numsurfaces;i++)
5261 edict = PRVM_EDICT_NUM(surfacelist[i]);
5262 switch ((int)edict->fields.server->solid)
5264 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5265 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5266 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5267 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5268 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5269 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5271 color[3] *= r_showbboxes.value;
5272 color[3] = bound(0, color[3], 1);
5273 GL_DepthTest(!r_showdisabledepthtest.integer);
5274 GL_CullFace(r_refdef.view.cullface_front);
5275 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5281 static void R_DrawEntityBBoxes(void)
5284 prvm_edict_t *edict;
5286 prvm_prog_t *prog_save = prog;
5288 // this function draws bounding boxes of server entities
5294 for (i = 0;i < prog->num_edicts;i++)
5296 edict = PRVM_EDICT_NUM(i);
5297 if (edict->priv.server->free)
5299 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5300 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5302 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5304 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5305 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5311 static const int nomodelelement3i[24] =
5323 static const unsigned short nomodelelement3s[24] =
5335 static const float nomodelvertex3f[6*3] =
5345 static const float nomodelcolor4f[6*4] =
5347 0.0f, 0.0f, 0.5f, 1.0f,
5348 0.0f, 0.0f, 0.5f, 1.0f,
5349 0.0f, 0.5f, 0.0f, 1.0f,
5350 0.0f, 0.5f, 0.0f, 1.0f,
5351 0.5f, 0.0f, 0.0f, 1.0f,
5352 0.5f, 0.0f, 0.0f, 1.0f
5355 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5361 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);
5363 // this is only called once per entity so numsurfaces is always 1, and
5364 // surfacelist is always {0}, so this code does not handle batches
5366 if (rsurface.ent_flags & RENDER_ADDITIVE)
5368 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5369 GL_DepthMask(false);
5371 else if (rsurface.ent_color[3] < 1)
5373 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5374 GL_DepthMask(false);
5378 GL_BlendFunc(GL_ONE, GL_ZERO);
5381 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5382 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5383 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5384 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5385 R_SetupGenericShader(false);
5386 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5387 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5388 R_Mesh_ColorPointer(color4f, 0, 0);
5389 for (i = 0, c = color4f;i < 6;i++, c += 4)
5391 c[0] *= rsurface.ent_color[0];
5392 c[1] *= rsurface.ent_color[1];
5393 c[2] *= rsurface.ent_color[2];
5394 c[3] *= rsurface.ent_color[3];
5396 if (r_refdef.fogenabled)
5398 for (i = 0, c = color4f;i < 6;i++, c += 4)
5400 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5402 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5403 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5404 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5407 R_Mesh_ResetTextureState();
5408 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5411 void R_DrawNoModel(entity_render_t *ent)
5414 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5415 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5416 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5418 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5421 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5423 vec3_t right1, right2, diff, normal;
5425 VectorSubtract (org2, org1, normal);
5427 // calculate 'right' vector for start
5428 VectorSubtract (r_refdef.view.origin, org1, diff);
5429 CrossProduct (normal, diff, right1);
5430 VectorNormalize (right1);
5432 // calculate 'right' vector for end
5433 VectorSubtract (r_refdef.view.origin, org2, diff);
5434 CrossProduct (normal, diff, right2);
5435 VectorNormalize (right2);
5437 vert[ 0] = org1[0] + width * right1[0];
5438 vert[ 1] = org1[1] + width * right1[1];
5439 vert[ 2] = org1[2] + width * right1[2];
5440 vert[ 3] = org1[0] - width * right1[0];
5441 vert[ 4] = org1[1] - width * right1[1];
5442 vert[ 5] = org1[2] - width * right1[2];
5443 vert[ 6] = org2[0] - width * right2[0];
5444 vert[ 7] = org2[1] - width * right2[1];
5445 vert[ 8] = org2[2] - width * right2[2];
5446 vert[ 9] = org2[0] + width * right2[0];
5447 vert[10] = org2[1] + width * right2[1];
5448 vert[11] = org2[2] + width * right2[2];
5451 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)
5453 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5454 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5455 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5456 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5457 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5458 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5459 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5460 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5461 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5462 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5463 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5464 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5467 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5472 VectorSet(v, x, y, z);
5473 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5474 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5476 if (i == mesh->numvertices)
5478 if (mesh->numvertices < mesh->maxvertices)
5480 VectorCopy(v, vertex3f);
5481 mesh->numvertices++;
5483 return mesh->numvertices;
5489 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5493 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5494 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5495 e = mesh->element3i + mesh->numtriangles * 3;
5496 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5498 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5499 if (mesh->numtriangles < mesh->maxtriangles)
5504 mesh->numtriangles++;
5506 element[1] = element[2];
5510 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5514 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5515 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5516 e = mesh->element3i + mesh->numtriangles * 3;
5517 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5519 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5520 if (mesh->numtriangles < mesh->maxtriangles)
5525 mesh->numtriangles++;
5527 element[1] = element[2];
5531 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5532 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5534 int planenum, planenum2;
5537 mplane_t *plane, *plane2;
5539 double temppoints[2][256*3];
5540 // figure out how large a bounding box we need to properly compute this brush
5542 for (w = 0;w < numplanes;w++)
5543 maxdist = max(maxdist, fabs(planes[w].dist));
5544 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5545 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5546 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5550 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5551 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5553 if (planenum2 == planenum)
5555 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);
5558 if (tempnumpoints < 3)
5560 // generate elements forming a triangle fan for this polygon
5561 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5565 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)
5567 texturelayer_t *layer;
5568 layer = t->currentlayers + t->currentnumlayers++;
5570 layer->depthmask = depthmask;
5571 layer->blendfunc1 = blendfunc1;
5572 layer->blendfunc2 = blendfunc2;
5573 layer->texture = texture;
5574 layer->texmatrix = *matrix;
5575 layer->color[0] = r * r_refdef.view.colorscale;
5576 layer->color[1] = g * r_refdef.view.colorscale;
5577 layer->color[2] = b * r_refdef.view.colorscale;
5578 layer->color[3] = a;
5581 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5584 index = parms[2] + r_refdef.scene.time * parms[3];
5585 index -= floor(index);
5589 case Q3WAVEFUNC_NONE:
5590 case Q3WAVEFUNC_NOISE:
5591 case Q3WAVEFUNC_COUNT:
5594 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5595 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5596 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5597 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5598 case Q3WAVEFUNC_TRIANGLE:
5600 f = index - floor(index);
5611 return (float)(parms[0] + parms[1] * f);
5614 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5619 matrix4x4_t matrix, temp;
5620 switch(tcmod->tcmod)
5624 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5625 matrix = r_waterscrollmatrix;
5627 matrix = identitymatrix;
5629 case Q3TCMOD_ENTITYTRANSLATE:
5630 // this is used in Q3 to allow the gamecode to control texcoord
5631 // scrolling on the entity, which is not supported in darkplaces yet.
5632 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5634 case Q3TCMOD_ROTATE:
5635 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5636 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5637 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5640 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5642 case Q3TCMOD_SCROLL:
5643 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5645 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5646 w = (int) tcmod->parms[0];
5647 h = (int) tcmod->parms[1];
5648 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5650 idx = (int) floor(f * w * h);
5651 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5653 case Q3TCMOD_STRETCH:
5654 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5655 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5657 case Q3TCMOD_TRANSFORM:
5658 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5659 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5660 VectorSet(tcmat + 6, 0 , 0 , 1);
5661 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5662 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5664 case Q3TCMOD_TURBULENT:
5665 // this is handled in the RSurf_PrepareVertices function
5666 matrix = identitymatrix;
5670 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5673 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5675 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5676 char name[MAX_QPATH];
5677 skinframe_t *skinframe;
5678 unsigned char pixels[296*194];
5679 strlcpy(cache->name, skinname, sizeof(cache->name));
5680 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5681 if (developer_loading.integer)
5682 Con_Printf("loading %s\n", name);
5683 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5684 if (!skinframe || !skinframe->base)
5687 fs_offset_t filesize;
5689 f = FS_LoadFile(name, tempmempool, true, &filesize);
5692 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5693 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5697 cache->skinframe = skinframe;
5700 texture_t *R_GetCurrentTexture(texture_t *t)
5703 const entity_render_t *ent = rsurface.entity;
5704 dp_model_t *model = ent->model;
5705 q3shaderinfo_layer_tcmod_t *tcmod;
5707 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5708 return t->currentframe;
5709 t->update_lastrenderframe = r_frame;
5710 t->update_lastrenderentity = (void *)ent;
5712 // switch to an alternate material if this is a q1bsp animated material
5714 texture_t *texture = t;
5715 int s = rsurface.ent_skinnum;
5716 if ((unsigned int)s >= (unsigned int)model->numskins)
5718 if (model->skinscenes)
5720 if (model->skinscenes[s].framecount > 1)
5721 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5723 s = model->skinscenes[s].firstframe;
5726 t = t + s * model->num_surfaces;
5729 // use an alternate animation if the entity's frame is not 0,
5730 // and only if the texture has an alternate animation
5731 if (rsurface.ent_alttextures && t->anim_total[1])
5732 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5734 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5736 texture->currentframe = t;
5739 // update currentskinframe to be a qw skin or animation frame
5740 if (rsurface.ent_qwskin >= 0)
5742 i = rsurface.ent_qwskin;
5743 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5745 r_qwskincache_size = cl.maxclients;
5747 Mem_Free(r_qwskincache);
5748 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5750 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5751 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5752 t->currentskinframe = r_qwskincache[i].skinframe;
5753 if (t->currentskinframe == NULL)
5754 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5756 else if (t->numskinframes >= 2)
5757 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5758 if (t->backgroundnumskinframes >= 2)
5759 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5761 t->currentmaterialflags = t->basematerialflags;
5762 t->currentalpha = rsurface.ent_color[3];
5763 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5764 t->currentalpha *= r_wateralpha.value;
5765 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5766 t->currentalpha *= t->r_water_wateralpha;
5767 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5768 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5769 if (!(rsurface.ent_flags & RENDER_LIGHT))
5770 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5771 else if (rsurface.modeltexcoordlightmap2f == NULL)
5773 // pick a model lighting mode
5774 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5775 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5777 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5779 if (rsurface.ent_flags & RENDER_ADDITIVE)
5780 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5781 else if (t->currentalpha < 1)
5782 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5783 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5784 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5785 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5786 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5787 if (t->backgroundnumskinframes)
5788 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5789 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5791 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5792 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5795 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5797 // there is no tcmod
5798 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5800 t->currenttexmatrix = r_waterscrollmatrix;
5801 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5803 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
5805 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5806 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5809 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5810 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5811 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5812 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5814 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5815 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5816 t->glosstexture = r_texture_black;
5817 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5818 t->backgroundglosstexture = r_texture_black;
5819 t->specularpower = r_shadow_glossexponent.value;
5820 // TODO: store reference values for these in the texture?
5821 t->specularscale = 0;
5822 if (r_shadow_gloss.integer > 0)
5824 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5826 if (r_shadow_glossintensity.value > 0)
5828 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5829 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5830 t->specularscale = r_shadow_glossintensity.value;
5833 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5835 t->glosstexture = r_texture_white;
5836 t->backgroundglosstexture = r_texture_white;
5837 t->specularscale = r_shadow_gloss2intensity.value;
5838 t->specularpower = r_shadow_gloss2exponent.value;
5841 t->specularscale *= t->specularscalemod;
5842 t->specularpower *= t->specularpowermod;
5844 // lightmaps mode looks bad with dlights using actual texturing, so turn
5845 // off the colormap and glossmap, but leave the normalmap on as it still
5846 // accurately represents the shading involved
5847 if (gl_lightmaps.integer)
5849 t->basetexture = r_texture_grey128;
5850 t->backgroundbasetexture = NULL;
5851 t->specularscale = 0;
5852 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5855 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5856 VectorClear(t->dlightcolor);
5857 t->currentnumlayers = 0;
5858 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5861 int blendfunc1, blendfunc2;
5863 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5865 blendfunc1 = GL_SRC_ALPHA;
5866 blendfunc2 = GL_ONE;
5868 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5870 blendfunc1 = GL_SRC_ALPHA;
5871 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5873 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5875 blendfunc1 = t->customblendfunc[0];
5876 blendfunc2 = t->customblendfunc[1];
5880 blendfunc1 = GL_ONE;
5881 blendfunc2 = GL_ZERO;
5883 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5884 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5885 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5886 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5888 // fullbright is not affected by r_refdef.lightmapintensity
5889 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]);
5890 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5891 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]);
5892 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5893 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]);
5897 vec3_t ambientcolor;
5899 // set the color tint used for lights affecting this surface
5900 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5902 // q3bsp has no lightmap updates, so the lightstylevalue that
5903 // would normally be baked into the lightmap must be
5904 // applied to the color
5905 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5906 if (model->type == mod_brushq3)
5907 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5908 colorscale *= r_refdef.lightmapintensity;
5909 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5910 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5911 // basic lit geometry
5912 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]);
5913 // add pants/shirt if needed
5914 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5915 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]);
5916 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5917 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]);
5918 // now add ambient passes if needed
5919 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5921 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]);
5922 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5923 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]);
5924 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5925 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]);
5928 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5929 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]);
5930 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5932 // if this is opaque use alpha blend which will darken the earlier
5935 // if this is an alpha blended material, all the earlier passes
5936 // were darkened by fog already, so we only need to add the fog
5937 // color ontop through the fog mask texture
5939 // if this is an additive blended material, all the earlier passes
5940 // were darkened by fog already, and we should not add fog color
5941 // (because the background was not darkened, there is no fog color
5942 // that was lost behind it).
5943 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]);
5947 return t->currentframe;
5950 rsurfacestate_t rsurface;
5952 void R_Mesh_ResizeArrays(int newvertices)
5955 if (rsurface.array_size >= newvertices)
5957 if (rsurface.array_modelvertex3f)
5958 Mem_Free(rsurface.array_modelvertex3f);
5959 rsurface.array_size = (newvertices + 1023) & ~1023;
5960 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5961 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5962 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5963 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5964 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5965 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5966 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5967 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5968 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5969 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5970 rsurface.array_color4f = base + rsurface.array_size * 27;
5971 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5974 void RSurf_ActiveWorldEntity(void)
5976 dp_model_t *model = r_refdef.scene.worldmodel;
5977 //if (rsurface.entity == r_refdef.scene.worldentity)
5979 rsurface.entity = r_refdef.scene.worldentity;
5980 rsurface.ent_skinnum = 0;
5981 rsurface.ent_qwskin = -1;
5982 rsurface.ent_shadertime = 0;
5983 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
5984 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
5985 if (rsurface.array_size < model->surfmesh.num_vertices)
5986 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5987 rsurface.matrix = identitymatrix;
5988 rsurface.inversematrix = identitymatrix;
5989 rsurface.matrixscale = 1;
5990 rsurface.inversematrixscale = 1;
5991 R_Mesh_Matrix(&identitymatrix);
5992 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5993 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
5994 rsurface.fograngerecip = r_refdef.fograngerecip;
5995 rsurface.fogheightfade = r_refdef.fogheightfade;
5996 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
5997 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
5998 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5999 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6000 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6001 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6002 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6003 VectorSet(rsurface.glowmod, 1, 1, 1);
6004 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6005 rsurface.frameblend[0].lerp = 1;
6006 rsurface.ent_alttextures = false;
6007 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6008 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6009 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6010 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6011 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6012 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6013 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6014 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6015 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6016 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6017 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6018 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6019 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6020 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6021 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6022 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6023 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6024 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6025 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6026 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6027 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6028 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6029 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6030 rsurface.modelelement3i = model->surfmesh.data_element3i;
6031 rsurface.modelelement3s = model->surfmesh.data_element3s;
6032 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6033 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6034 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6035 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6036 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6037 rsurface.modelsurfaces = model->data_surfaces;
6038 rsurface.generatedvertex = false;
6039 rsurface.vertex3f = rsurface.modelvertex3f;
6040 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6041 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6042 rsurface.svector3f = rsurface.modelsvector3f;
6043 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6044 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6045 rsurface.tvector3f = rsurface.modeltvector3f;
6046 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6047 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6048 rsurface.normal3f = rsurface.modelnormal3f;
6049 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6050 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6051 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6054 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6056 dp_model_t *model = ent->model;
6057 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6059 rsurface.entity = (entity_render_t *)ent;
6060 rsurface.ent_skinnum = ent->skinnum;
6061 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;
6062 rsurface.ent_shadertime = ent->shadertime;
6063 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6064 rsurface.ent_flags = ent->flags;
6065 if (rsurface.array_size < model->surfmesh.num_vertices)
6066 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6067 rsurface.matrix = ent->matrix;
6068 rsurface.inversematrix = ent->inversematrix;
6069 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6070 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6071 R_Mesh_Matrix(&rsurface.matrix);
6072 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6073 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6074 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6075 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6076 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6077 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6078 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6079 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6080 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6081 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6082 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6083 VectorCopy(ent->glowmod, rsurface.glowmod);
6084 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6085 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6086 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6087 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6088 if (ent->model->brush.submodel)
6090 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6091 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6093 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6095 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6097 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6098 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6099 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6100 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6102 else if (wanttangents)
6104 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6105 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6106 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6107 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6108 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6110 else if (wantnormals)
6112 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6113 rsurface.modelsvector3f = NULL;
6114 rsurface.modeltvector3f = NULL;
6115 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6116 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6120 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6121 rsurface.modelsvector3f = NULL;
6122 rsurface.modeltvector3f = NULL;
6123 rsurface.modelnormal3f = NULL;
6124 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6126 rsurface.modelvertex3f_bufferobject = 0;
6127 rsurface.modelvertex3f_bufferoffset = 0;
6128 rsurface.modelsvector3f_bufferobject = 0;
6129 rsurface.modelsvector3f_bufferoffset = 0;
6130 rsurface.modeltvector3f_bufferobject = 0;
6131 rsurface.modeltvector3f_bufferoffset = 0;
6132 rsurface.modelnormal3f_bufferobject = 0;
6133 rsurface.modelnormal3f_bufferoffset = 0;
6134 rsurface.generatedvertex = true;
6138 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6139 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6140 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6141 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6142 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6143 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6144 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6145 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6146 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6147 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6148 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6149 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6150 rsurface.generatedvertex = false;
6152 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6153 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6154 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6155 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6156 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6157 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6158 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6159 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6160 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6161 rsurface.modelelement3i = model->surfmesh.data_element3i;
6162 rsurface.modelelement3s = model->surfmesh.data_element3s;
6163 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6164 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6165 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6166 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6167 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6168 rsurface.modelsurfaces = model->data_surfaces;
6169 rsurface.vertex3f = rsurface.modelvertex3f;
6170 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6171 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6172 rsurface.svector3f = rsurface.modelsvector3f;
6173 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6174 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6175 rsurface.tvector3f = rsurface.modeltvector3f;
6176 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6177 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6178 rsurface.normal3f = rsurface.modelnormal3f;
6179 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6180 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6181 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6184 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)
6186 rsurface.entity = r_refdef.scene.worldentity;
6187 rsurface.ent_skinnum = 0;
6188 rsurface.ent_qwskin = -1;
6189 rsurface.ent_shadertime = shadertime;
6190 Vector4Set(rsurface.ent_color, r, g, b, a);
6191 rsurface.ent_flags = entflags;
6192 rsurface.modelnum_vertices = numvertices;
6193 rsurface.modelnum_triangles = numtriangles;
6194 if (rsurface.array_size < rsurface.modelnum_vertices)
6195 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6196 rsurface.matrix = *matrix;
6197 rsurface.inversematrix = *inversematrix;
6198 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6199 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6200 R_Mesh_Matrix(&rsurface.matrix);
6201 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6202 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6203 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6204 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6205 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6206 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6207 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6208 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6209 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6210 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6211 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6212 VectorSet(rsurface.glowmod, 1, 1, 1);
6213 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6214 rsurface.frameblend[0].lerp = 1;
6215 rsurface.ent_alttextures = false;
6216 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6217 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6220 rsurface.modelvertex3f = vertex3f;
6221 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6222 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6223 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6225 else if (wantnormals)
6227 rsurface.modelvertex3f = vertex3f;
6228 rsurface.modelsvector3f = NULL;
6229 rsurface.modeltvector3f = NULL;
6230 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6234 rsurface.modelvertex3f = vertex3f;
6235 rsurface.modelsvector3f = NULL;
6236 rsurface.modeltvector3f = NULL;
6237 rsurface.modelnormal3f = NULL;
6239 rsurface.modelvertex3f_bufferobject = 0;
6240 rsurface.modelvertex3f_bufferoffset = 0;
6241 rsurface.modelsvector3f_bufferobject = 0;
6242 rsurface.modelsvector3f_bufferoffset = 0;
6243 rsurface.modeltvector3f_bufferobject = 0;
6244 rsurface.modeltvector3f_bufferoffset = 0;
6245 rsurface.modelnormal3f_bufferobject = 0;
6246 rsurface.modelnormal3f_bufferoffset = 0;
6247 rsurface.generatedvertex = true;
6248 rsurface.modellightmapcolor4f = color4f;
6249 rsurface.modellightmapcolor4f_bufferobject = 0;
6250 rsurface.modellightmapcolor4f_bufferoffset = 0;
6251 rsurface.modeltexcoordtexture2f = texcoord2f;
6252 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6253 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6254 rsurface.modeltexcoordlightmap2f = NULL;
6255 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6256 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6257 rsurface.modelelement3i = element3i;
6258 rsurface.modelelement3s = element3s;
6259 rsurface.modelelement3i_bufferobject = 0;
6260 rsurface.modelelement3s_bufferobject = 0;
6261 rsurface.modellightmapoffsets = NULL;
6262 rsurface.modelsurfaces = NULL;
6263 rsurface.vertex3f = rsurface.modelvertex3f;
6264 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6265 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6266 rsurface.svector3f = rsurface.modelsvector3f;
6267 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6268 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6269 rsurface.tvector3f = rsurface.modeltvector3f;
6270 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6271 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6272 rsurface.normal3f = rsurface.modelnormal3f;
6273 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6274 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6275 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6277 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6279 if ((wantnormals || wanttangents) && !normal3f)
6280 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6281 if (wanttangents && !svector3f)
6282 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);
6286 float RSurf_FogPoint(const float *v)
6288 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6289 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6290 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6291 float FogHeightFade = r_refdef.fogheightfade;
6293 unsigned int fogmasktableindex;
6294 if (r_refdef.fogplaneviewabove)
6295 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6297 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6298 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6299 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6302 float RSurf_FogVertex(const float *v)
6304 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6305 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6306 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6307 float FogHeightFade = rsurface.fogheightfade;
6309 unsigned int fogmasktableindex;
6310 if (r_refdef.fogplaneviewabove)
6311 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6313 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6314 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6315 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6318 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6319 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6322 int texturesurfaceindex;
6327 const float *v1, *in_tc;
6329 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6331 q3shaderinfo_deform_t *deform;
6332 // 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
6333 if (rsurface.generatedvertex)
6335 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6336 generatenormals = true;
6337 for (i = 0;i < Q3MAXDEFORMS;i++)
6339 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6341 generatetangents = true;
6342 generatenormals = true;
6344 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6345 generatenormals = true;
6347 if (generatenormals && !rsurface.modelnormal3f)
6349 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6350 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6351 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6352 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6354 if (generatetangents && !rsurface.modelsvector3f)
6356 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6357 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6358 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6359 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6360 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6361 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6362 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);
6365 rsurface.vertex3f = rsurface.modelvertex3f;
6366 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6367 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6368 rsurface.svector3f = rsurface.modelsvector3f;
6369 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6370 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6371 rsurface.tvector3f = rsurface.modeltvector3f;
6372 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6373 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6374 rsurface.normal3f = rsurface.modelnormal3f;
6375 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6376 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6377 // if vertices are deformed (sprite flares and things in maps, possibly
6378 // water waves, bulges and other deformations), generate them into
6379 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6380 // (may be static model data or generated data for an animated model, or
6381 // the previous deform pass)
6382 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6384 switch (deform->deform)
6387 case Q3DEFORM_PROJECTIONSHADOW:
6388 case Q3DEFORM_TEXT0:
6389 case Q3DEFORM_TEXT1:
6390 case Q3DEFORM_TEXT2:
6391 case Q3DEFORM_TEXT3:
6392 case Q3DEFORM_TEXT4:
6393 case Q3DEFORM_TEXT5:
6394 case Q3DEFORM_TEXT6:
6395 case Q3DEFORM_TEXT7:
6398 case Q3DEFORM_AUTOSPRITE:
6399 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6400 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6401 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6402 VectorNormalize(newforward);
6403 VectorNormalize(newright);
6404 VectorNormalize(newup);
6405 // make deformed versions of only the model vertices used by the specified surfaces
6406 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6408 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6409 // a single autosprite surface can contain multiple sprites...
6410 for (j = 0;j < surface->num_vertices - 3;j += 4)
6412 VectorClear(center);
6413 for (i = 0;i < 4;i++)
6414 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6415 VectorScale(center, 0.25f, center);
6416 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6417 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6418 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6419 for (i = 0;i < 4;i++)
6421 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6422 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6425 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);
6426 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);
6428 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6429 rsurface.vertex3f_bufferobject = 0;
6430 rsurface.vertex3f_bufferoffset = 0;
6431 rsurface.svector3f = rsurface.array_deformedsvector3f;
6432 rsurface.svector3f_bufferobject = 0;
6433 rsurface.svector3f_bufferoffset = 0;
6434 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6435 rsurface.tvector3f_bufferobject = 0;
6436 rsurface.tvector3f_bufferoffset = 0;
6437 rsurface.normal3f = rsurface.array_deformednormal3f;
6438 rsurface.normal3f_bufferobject = 0;
6439 rsurface.normal3f_bufferoffset = 0;
6441 case Q3DEFORM_AUTOSPRITE2:
6442 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6443 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6444 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6445 VectorNormalize(newforward);
6446 VectorNormalize(newright);
6447 VectorNormalize(newup);
6448 // make deformed versions of only the model vertices used by the specified surfaces
6449 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6451 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6452 const float *v1, *v2;
6462 memset(shortest, 0, sizeof(shortest));
6463 // a single autosprite surface can contain multiple sprites...
6464 for (j = 0;j < surface->num_vertices - 3;j += 4)
6466 VectorClear(center);
6467 for (i = 0;i < 4;i++)
6468 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6469 VectorScale(center, 0.25f, center);
6470 // find the two shortest edges, then use them to define the
6471 // axis vectors for rotating around the central axis
6472 for (i = 0;i < 6;i++)
6474 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6475 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6477 Debug_PolygonBegin(NULL, 0);
6478 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6479 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);
6480 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6483 l = VectorDistance2(v1, v2);
6484 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6486 l += (1.0f / 1024.0f);
6487 if (shortest[0].length2 > l || i == 0)
6489 shortest[1] = shortest[0];
6490 shortest[0].length2 = l;
6491 shortest[0].v1 = v1;
6492 shortest[0].v2 = v2;
6494 else if (shortest[1].length2 > l || i == 1)
6496 shortest[1].length2 = l;
6497 shortest[1].v1 = v1;
6498 shortest[1].v2 = v2;
6501 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6502 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6504 Debug_PolygonBegin(NULL, 0);
6505 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6506 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);
6507 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6510 // this calculates the right vector from the shortest edge
6511 // and the up vector from the edge midpoints
6512 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6513 VectorNormalize(right);
6514 VectorSubtract(end, start, up);
6515 VectorNormalize(up);
6516 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6517 VectorSubtract(rsurface.localvieworigin, center, forward);
6518 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6519 VectorNegate(forward, forward);
6520 VectorReflect(forward, 0, up, forward);
6521 VectorNormalize(forward);
6522 CrossProduct(up, forward, newright);
6523 VectorNormalize(newright);
6525 Debug_PolygonBegin(NULL, 0);
6526 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);
6527 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6528 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6532 Debug_PolygonBegin(NULL, 0);
6533 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6534 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6535 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6538 // rotate the quad around the up axis vector, this is made
6539 // especially easy by the fact we know the quad is flat,
6540 // so we only have to subtract the center position and
6541 // measure distance along the right vector, and then
6542 // multiply that by the newright vector and add back the
6544 // we also need to subtract the old position to undo the
6545 // displacement from the center, which we do with a
6546 // DotProduct, the subtraction/addition of center is also
6547 // optimized into DotProducts here
6548 l = DotProduct(right, center);
6549 for (i = 0;i < 4;i++)
6551 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6552 f = DotProduct(right, v1) - l;
6553 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6556 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);
6557 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);
6559 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6560 rsurface.vertex3f_bufferobject = 0;
6561 rsurface.vertex3f_bufferoffset = 0;
6562 rsurface.svector3f = rsurface.array_deformedsvector3f;
6563 rsurface.svector3f_bufferobject = 0;
6564 rsurface.svector3f_bufferoffset = 0;
6565 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6566 rsurface.tvector3f_bufferobject = 0;
6567 rsurface.tvector3f_bufferoffset = 0;
6568 rsurface.normal3f = rsurface.array_deformednormal3f;
6569 rsurface.normal3f_bufferobject = 0;
6570 rsurface.normal3f_bufferoffset = 0;
6572 case Q3DEFORM_NORMAL:
6573 // deform the normals to make reflections wavey
6574 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6576 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6577 for (j = 0;j < surface->num_vertices;j++)
6580 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6581 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6582 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6583 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6584 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6585 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6586 VectorNormalize(normal);
6588 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);
6590 rsurface.svector3f = rsurface.array_deformedsvector3f;
6591 rsurface.svector3f_bufferobject = 0;
6592 rsurface.svector3f_bufferoffset = 0;
6593 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6594 rsurface.tvector3f_bufferobject = 0;
6595 rsurface.tvector3f_bufferoffset = 0;
6596 rsurface.normal3f = rsurface.array_deformednormal3f;
6597 rsurface.normal3f_bufferobject = 0;
6598 rsurface.normal3f_bufferoffset = 0;
6601 // deform vertex array to make wavey water and flags and such
6602 waveparms[0] = deform->waveparms[0];
6603 waveparms[1] = deform->waveparms[1];
6604 waveparms[2] = deform->waveparms[2];
6605 waveparms[3] = deform->waveparms[3];
6606 // this is how a divisor of vertex influence on deformation
6607 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6608 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6609 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6611 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6612 for (j = 0;j < surface->num_vertices;j++)
6614 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6615 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6616 // if the wavefunc depends on time, evaluate it per-vertex
6619 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6620 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6622 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6625 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6626 rsurface.vertex3f_bufferobject = 0;
6627 rsurface.vertex3f_bufferoffset = 0;
6629 case Q3DEFORM_BULGE:
6630 // deform vertex array to make the surface have moving bulges
6631 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6633 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6634 for (j = 0;j < surface->num_vertices;j++)
6636 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6637 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6640 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6641 rsurface.vertex3f_bufferobject = 0;
6642 rsurface.vertex3f_bufferoffset = 0;
6645 // deform vertex array
6646 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6647 VectorScale(deform->parms, scale, waveparms);
6648 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6650 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6651 for (j = 0;j < surface->num_vertices;j++)
6652 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6654 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6655 rsurface.vertex3f_bufferobject = 0;
6656 rsurface.vertex3f_bufferoffset = 0;
6660 // generate texcoords based on the chosen texcoord source
6661 switch(rsurface.texture->tcgen.tcgen)
6664 case Q3TCGEN_TEXTURE:
6665 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6666 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6667 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6669 case Q3TCGEN_LIGHTMAP:
6670 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6671 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6672 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6674 case Q3TCGEN_VECTOR:
6675 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6677 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6678 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)
6680 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6681 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6684 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6685 rsurface.texcoordtexture2f_bufferobject = 0;
6686 rsurface.texcoordtexture2f_bufferoffset = 0;
6688 case Q3TCGEN_ENVIRONMENT:
6689 // make environment reflections using a spheremap
6690 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6692 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6693 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6694 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6695 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6696 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6698 // identical to Q3A's method, but executed in worldspace so
6699 // carried models can be shiny too
6701 float viewer[3], d, reflected[3], worldreflected[3];
6703 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6704 // VectorNormalize(viewer);
6706 d = DotProduct(normal, viewer);
6708 reflected[0] = normal[0]*2*d - viewer[0];
6709 reflected[1] = normal[1]*2*d - viewer[1];
6710 reflected[2] = normal[2]*2*d - viewer[2];
6711 // note: this is proportinal to viewer, so we can normalize later
6713 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6714 VectorNormalize(worldreflected);
6716 // note: this sphere map only uses world x and z!
6717 // so positive and negative y will LOOK THE SAME.
6718 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6719 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6722 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6723 rsurface.texcoordtexture2f_bufferobject = 0;
6724 rsurface.texcoordtexture2f_bufferoffset = 0;
6727 // the only tcmod that needs software vertex processing is turbulent, so
6728 // check for it here and apply the changes if needed
6729 // and we only support that as the first one
6730 // (handling a mixture of turbulent and other tcmods would be problematic
6731 // without punting it entirely to a software path)
6732 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6734 amplitude = rsurface.texture->tcmods[0].parms[1];
6735 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6736 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6738 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6739 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)
6741 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6742 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6745 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6746 rsurface.texcoordtexture2f_bufferobject = 0;
6747 rsurface.texcoordtexture2f_bufferoffset = 0;
6749 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6750 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6751 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6752 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6755 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6758 const msurface_t *surface = texturesurfacelist[0];
6759 const msurface_t *surface2;
6764 // TODO: lock all array ranges before render, rather than on each surface
6765 if (texturenumsurfaces == 1)
6767 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6768 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);
6770 else if (r_batchmode.integer == 2)
6772 #define MAXBATCHTRIANGLES 4096
6773 int batchtriangles = 0;
6774 int batchelements[MAXBATCHTRIANGLES*3];
6775 for (i = 0;i < texturenumsurfaces;i = j)
6777 surface = texturesurfacelist[i];
6779 if (surface->num_triangles > MAXBATCHTRIANGLES)
6781 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);
6784 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6785 batchtriangles = surface->num_triangles;
6786 firstvertex = surface->num_firstvertex;
6787 endvertex = surface->num_firstvertex + surface->num_vertices;
6788 for (;j < texturenumsurfaces;j++)
6790 surface2 = texturesurfacelist[j];
6791 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6793 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6794 batchtriangles += surface2->num_triangles;
6795 firstvertex = min(firstvertex, surface2->num_firstvertex);
6796 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6798 surface2 = texturesurfacelist[j-1];
6799 numvertices = endvertex - firstvertex;
6800 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6803 else if (r_batchmode.integer == 1)
6805 for (i = 0;i < texturenumsurfaces;i = j)
6807 surface = texturesurfacelist[i];
6808 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6809 if (texturesurfacelist[j] != surface2)
6811 surface2 = texturesurfacelist[j-1];
6812 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6813 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6814 GL_LockArrays(surface->num_firstvertex, numvertices);
6815 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6820 for (i = 0;i < texturenumsurfaces;i++)
6822 surface = texturesurfacelist[i];
6823 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6824 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6829 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6831 int i, planeindex, vertexindex;
6835 r_waterstate_waterplane_t *p, *bestp;
6836 const msurface_t *surface;
6837 if (r_waterstate.renderingscene)
6839 for (i = 0;i < texturenumsurfaces;i++)
6841 surface = texturesurfacelist[i];
6842 if (lightmaptexunit >= 0)
6843 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6844 if (deluxemaptexunit >= 0)
6845 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6846 // pick the closest matching water plane
6849 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6852 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6854 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6855 d += fabs(PlaneDiff(vert, &p->plane));
6857 if (bestd > d || !bestp)
6865 if (refractiontexunit >= 0)
6866 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6867 if (reflectiontexunit >= 0)
6868 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6872 if (refractiontexunit >= 0)
6873 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6874 if (reflectiontexunit >= 0)
6875 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6877 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6878 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);
6882 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6886 const msurface_t *surface = texturesurfacelist[0];
6887 const msurface_t *surface2;
6892 // TODO: lock all array ranges before render, rather than on each surface
6893 if (texturenumsurfaces == 1)
6895 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6896 if (deluxemaptexunit >= 0)
6897 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6898 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6899 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);
6901 else if (r_batchmode.integer == 2)
6903 #define MAXBATCHTRIANGLES 4096
6904 int batchtriangles = 0;
6905 int batchelements[MAXBATCHTRIANGLES*3];
6906 for (i = 0;i < texturenumsurfaces;i = j)
6908 surface = texturesurfacelist[i];
6909 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6910 if (deluxemaptexunit >= 0)
6911 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6913 if (surface->num_triangles > MAXBATCHTRIANGLES)
6915 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);
6918 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6919 batchtriangles = surface->num_triangles;
6920 firstvertex = surface->num_firstvertex;
6921 endvertex = surface->num_firstvertex + surface->num_vertices;
6922 for (;j < texturenumsurfaces;j++)
6924 surface2 = texturesurfacelist[j];
6925 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6927 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6928 batchtriangles += surface2->num_triangles;
6929 firstvertex = min(firstvertex, surface2->num_firstvertex);
6930 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6932 surface2 = texturesurfacelist[j-1];
6933 numvertices = endvertex - firstvertex;
6934 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6937 else if (r_batchmode.integer == 1)
6940 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6941 for (i = 0;i < texturenumsurfaces;i = j)
6943 surface = texturesurfacelist[i];
6944 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6945 if (texturesurfacelist[j] != surface2)
6947 Con_Printf(" %i", j - i);
6950 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6952 for (i = 0;i < texturenumsurfaces;i = j)
6954 surface = texturesurfacelist[i];
6955 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6956 if (deluxemaptexunit >= 0)
6957 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6958 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6959 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6962 Con_Printf(" %i", j - i);
6964 surface2 = texturesurfacelist[j-1];
6965 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6966 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6967 GL_LockArrays(surface->num_firstvertex, numvertices);
6968 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6976 for (i = 0;i < texturenumsurfaces;i++)
6978 surface = texturesurfacelist[i];
6979 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6980 if (deluxemaptexunit >= 0)
6981 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6982 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6983 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);
6988 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6991 int texturesurfaceindex;
6992 if (r_showsurfaces.integer == 2)
6994 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6996 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6997 for (j = 0;j < surface->num_triangles;j++)
6999 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7000 GL_Color(f, f, f, 1);
7001 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7007 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7009 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7010 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7011 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);
7012 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7013 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);
7018 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7020 int texturesurfaceindex;
7024 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7026 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7027 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)
7035 rsurface.lightmapcolor4f = rsurface.array_color4f;
7036 rsurface.lightmapcolor4f_bufferobject = 0;
7037 rsurface.lightmapcolor4f_bufferoffset = 0;
7040 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7042 int texturesurfaceindex;
7048 if (rsurface.lightmapcolor4f)
7050 // generate color arrays for the surfaces in this list
7051 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7053 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7054 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)
7056 f = RSurf_FogVertex(v);
7066 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7068 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7069 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)
7071 f = RSurf_FogVertex(v);
7079 rsurface.lightmapcolor4f = rsurface.array_color4f;
7080 rsurface.lightmapcolor4f_bufferobject = 0;
7081 rsurface.lightmapcolor4f_bufferoffset = 0;
7084 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7086 int texturesurfaceindex;
7092 if (!rsurface.lightmapcolor4f)
7094 // generate color arrays for the surfaces in this list
7095 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7097 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7098 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), 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)
7100 f = RSurf_FogVertex(v);
7101 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7102 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7103 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7107 rsurface.lightmapcolor4f = rsurface.array_color4f;
7108 rsurface.lightmapcolor4f_bufferobject = 0;
7109 rsurface.lightmapcolor4f_bufferoffset = 0;
7112 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7114 int texturesurfaceindex;
7118 if (!rsurface.lightmapcolor4f)
7120 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7122 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7123 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)
7131 rsurface.lightmapcolor4f = rsurface.array_color4f;
7132 rsurface.lightmapcolor4f_bufferobject = 0;
7133 rsurface.lightmapcolor4f_bufferoffset = 0;
7136 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7138 int texturesurfaceindex;
7142 if (!rsurface.lightmapcolor4f)
7144 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7146 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7147 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)
7149 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7150 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7151 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7155 rsurface.lightmapcolor4f = rsurface.array_color4f;
7156 rsurface.lightmapcolor4f_bufferobject = 0;
7157 rsurface.lightmapcolor4f_bufferoffset = 0;
7160 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7163 rsurface.lightmapcolor4f = NULL;
7164 rsurface.lightmapcolor4f_bufferobject = 0;
7165 rsurface.lightmapcolor4f_bufferoffset = 0;
7166 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7167 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7168 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7169 GL_Color(r, g, b, a);
7170 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7173 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7175 // TODO: optimize applyfog && applycolor case
7176 // just apply fog if necessary, and tint the fog color array if necessary
7177 rsurface.lightmapcolor4f = NULL;
7178 rsurface.lightmapcolor4f_bufferobject = 0;
7179 rsurface.lightmapcolor4f_bufferoffset = 0;
7180 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7181 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7182 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7183 GL_Color(r, g, b, a);
7184 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7187 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7189 int texturesurfaceindex;
7193 if (texturesurfacelist[0]->lightmapinfo)
7195 // generate color arrays for the surfaces in this list
7196 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7198 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7199 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7201 if (surface->lightmapinfo->samples)
7203 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7204 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7205 VectorScale(lm, scale, c);
7206 if (surface->lightmapinfo->styles[1] != 255)
7208 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7210 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7211 VectorMA(c, scale, lm, c);
7212 if (surface->lightmapinfo->styles[2] != 255)
7215 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7216 VectorMA(c, scale, lm, c);
7217 if (surface->lightmapinfo->styles[3] != 255)
7220 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7221 VectorMA(c, scale, lm, c);
7231 rsurface.lightmapcolor4f = rsurface.array_color4f;
7232 rsurface.lightmapcolor4f_bufferobject = 0;
7233 rsurface.lightmapcolor4f_bufferoffset = 0;
7237 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7238 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7239 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7241 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7242 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7243 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7244 GL_Color(r, g, b, a);
7245 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7248 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7250 int texturesurfaceindex;
7257 vec3_t ambientcolor;
7258 vec3_t diffusecolor;
7262 VectorCopy(rsurface.modellight_lightdir, lightdir);
7263 f = 0.5f * r_refdef.lightmapintensity;
7264 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7265 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7266 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7267 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7268 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7269 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7271 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7273 // generate color arrays for the surfaces in this list
7274 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7276 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7277 int numverts = surface->num_vertices;
7278 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7279 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7280 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7281 // q3-style directional shading
7282 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7284 if ((f = DotProduct(n, lightdir)) > 0)
7285 VectorMA(ambientcolor, f, diffusecolor, c);
7287 VectorCopy(ambientcolor, c);
7295 rsurface.lightmapcolor4f = rsurface.array_color4f;
7296 rsurface.lightmapcolor4f_bufferobject = 0;
7297 rsurface.lightmapcolor4f_bufferoffset = 0;
7298 *applycolor = false;
7302 *r = ambientcolor[0];
7303 *g = ambientcolor[1];
7304 *b = ambientcolor[2];
7305 rsurface.lightmapcolor4f = NULL;
7306 rsurface.lightmapcolor4f_bufferobject = 0;
7307 rsurface.lightmapcolor4f_bufferoffset = 0;
7311 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7313 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7314 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7315 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7316 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7317 GL_Color(r, g, b, a);
7318 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7321 void RSurf_SetupDepthAndCulling(void)
7323 // submodels are biased to avoid z-fighting with world surfaces that they
7324 // may be exactly overlapping (avoids z-fighting artifacts on certain
7325 // doors and things in Quake maps)
7326 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7327 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7328 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7329 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7332 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7334 // transparent sky would be ridiculous
7335 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7337 R_SetupGenericShader(false);
7338 skyrenderlater = true;
7339 RSurf_SetupDepthAndCulling();
7341 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7342 // skymasking on them, and Quake3 never did sky masking (unlike
7343 // software Quake and software Quake2), so disable the sky masking
7344 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7345 // and skymasking also looks very bad when noclipping outside the
7346 // level, so don't use it then either.
7347 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7349 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7350 R_Mesh_ColorPointer(NULL, 0, 0);
7351 R_Mesh_ResetTextureState();
7352 if (skyrendermasked)
7354 R_SetupDepthOrShadowShader();
7355 // depth-only (masking)
7356 GL_ColorMask(0,0,0,0);
7357 // just to make sure that braindead drivers don't draw
7358 // anything despite that colormask...
7359 GL_BlendFunc(GL_ZERO, GL_ONE);
7363 R_SetupGenericShader(false);
7365 GL_BlendFunc(GL_ONE, GL_ZERO);
7367 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7368 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7369 if (skyrendermasked)
7370 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7372 R_Mesh_ResetTextureState();
7373 GL_Color(1, 1, 1, 1);
7376 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7378 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7381 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7382 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7383 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7384 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7385 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7386 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7387 if (rsurface.texture->backgroundcurrentskinframe)
7389 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7390 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7391 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7392 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7394 if(rsurface.texture->colormapping)
7396 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7397 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7399 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7400 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7401 R_Mesh_ColorPointer(NULL, 0, 0);
7403 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7405 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7407 // render background
7408 GL_BlendFunc(GL_ONE, GL_ZERO);
7410 GL_AlphaTest(false);
7412 GL_Color(1, 1, 1, 1);
7413 R_Mesh_ColorPointer(NULL, 0, 0);
7415 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7416 if (r_glsl_permutation)
7418 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7419 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7420 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7421 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7422 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7423 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7424 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);
7426 GL_LockArrays(0, 0);
7428 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7429 GL_DepthMask(false);
7430 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7431 R_Mesh_ColorPointer(NULL, 0, 0);
7433 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7434 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7435 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7438 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7439 if (!r_glsl_permutation)
7442 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7443 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7444 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7445 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7446 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7447 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7449 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7451 GL_BlendFunc(GL_ONE, GL_ZERO);
7453 GL_AlphaTest(false);
7457 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7458 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7459 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7462 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7464 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7465 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);
7467 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7471 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7472 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);
7474 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7476 GL_LockArrays(0, 0);
7479 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7481 // OpenGL 1.3 path - anything not completely ancient
7482 int texturesurfaceindex;
7483 qboolean applycolor;
7487 const texturelayer_t *layer;
7488 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7490 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7493 int layertexrgbscale;
7494 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7496 if (layerindex == 0)
7500 GL_AlphaTest(false);
7501 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7504 GL_DepthMask(layer->depthmask && writedepth);
7505 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7506 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7508 layertexrgbscale = 4;
7509 VectorScale(layer->color, 0.25f, layercolor);
7511 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7513 layertexrgbscale = 2;
7514 VectorScale(layer->color, 0.5f, layercolor);
7518 layertexrgbscale = 1;
7519 VectorScale(layer->color, 1.0f, layercolor);
7521 layercolor[3] = layer->color[3];
7522 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7523 R_Mesh_ColorPointer(NULL, 0, 0);
7524 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7525 switch (layer->type)
7527 case TEXTURELAYERTYPE_LITTEXTURE:
7528 memset(&m, 0, sizeof(m));
7529 m.tex[0] = R_GetTexture(r_texture_white);
7530 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7531 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7532 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7533 m.tex[1] = R_GetTexture(layer->texture);
7534 m.texmatrix[1] = layer->texmatrix;
7535 m.texrgbscale[1] = layertexrgbscale;
7536 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7537 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7538 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7539 R_Mesh_TextureState(&m);
7540 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7541 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7542 else if (rsurface.uselightmaptexture)
7543 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7545 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7547 case TEXTURELAYERTYPE_TEXTURE:
7548 memset(&m, 0, sizeof(m));
7549 m.tex[0] = R_GetTexture(layer->texture);
7550 m.texmatrix[0] = layer->texmatrix;
7551 m.texrgbscale[0] = layertexrgbscale;
7552 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7553 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7554 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7555 R_Mesh_TextureState(&m);
7556 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7558 case TEXTURELAYERTYPE_FOG:
7559 memset(&m, 0, sizeof(m));
7560 m.texrgbscale[0] = layertexrgbscale;
7563 m.tex[0] = R_GetTexture(layer->texture);
7564 m.texmatrix[0] = layer->texmatrix;
7565 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7566 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7567 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7569 R_Mesh_TextureState(&m);
7570 // generate a color array for the fog pass
7571 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7572 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7578 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7579 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)
7581 f = 1 - RSurf_FogVertex(v);
7582 c[0] = layercolor[0];
7583 c[1] = layercolor[1];
7584 c[2] = layercolor[2];
7585 c[3] = f * layercolor[3];
7588 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7591 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7593 GL_LockArrays(0, 0);
7596 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7598 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7599 GL_AlphaTest(false);
7603 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7605 // OpenGL 1.1 - crusty old voodoo path
7606 int texturesurfaceindex;
7610 const texturelayer_t *layer;
7611 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7613 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7615 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7617 if (layerindex == 0)
7621 GL_AlphaTest(false);
7622 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7625 GL_DepthMask(layer->depthmask && writedepth);
7626 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7627 R_Mesh_ColorPointer(NULL, 0, 0);
7628 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7629 switch (layer->type)
7631 case TEXTURELAYERTYPE_LITTEXTURE:
7632 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7634 // two-pass lit texture with 2x rgbscale
7635 // first the lightmap pass
7636 memset(&m, 0, sizeof(m));
7637 m.tex[0] = R_GetTexture(r_texture_white);
7638 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7639 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7640 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7641 R_Mesh_TextureState(&m);
7642 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7643 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7644 else if (rsurface.uselightmaptexture)
7645 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7647 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7648 GL_LockArrays(0, 0);
7649 // then apply the texture to it
7650 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7651 memset(&m, 0, sizeof(m));
7652 m.tex[0] = R_GetTexture(layer->texture);
7653 m.texmatrix[0] = layer->texmatrix;
7654 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7655 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7656 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7657 R_Mesh_TextureState(&m);
7658 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);
7662 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7663 memset(&m, 0, sizeof(m));
7664 m.tex[0] = R_GetTexture(layer->texture);
7665 m.texmatrix[0] = layer->texmatrix;
7666 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7667 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7668 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7669 R_Mesh_TextureState(&m);
7670 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7671 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);
7673 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);
7676 case TEXTURELAYERTYPE_TEXTURE:
7677 // singletexture unlit texture with transparency support
7678 memset(&m, 0, sizeof(m));
7679 m.tex[0] = R_GetTexture(layer->texture);
7680 m.texmatrix[0] = layer->texmatrix;
7681 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7682 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7683 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7684 R_Mesh_TextureState(&m);
7685 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);
7687 case TEXTURELAYERTYPE_FOG:
7688 // singletexture fogging
7689 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7692 memset(&m, 0, sizeof(m));
7693 m.tex[0] = R_GetTexture(layer->texture);
7694 m.texmatrix[0] = layer->texmatrix;
7695 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7696 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7697 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7698 R_Mesh_TextureState(&m);
7701 R_Mesh_ResetTextureState();
7702 // generate a color array for the fog pass
7703 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7709 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7710 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)
7712 f = 1 - RSurf_FogVertex(v);
7713 c[0] = layer->color[0];
7714 c[1] = layer->color[1];
7715 c[2] = layer->color[2];
7716 c[3] = f * layer->color[3];
7719 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7722 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7724 GL_LockArrays(0, 0);
7727 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7729 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7730 GL_AlphaTest(false);
7734 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7738 GL_AlphaTest(false);
7739 R_Mesh_ColorPointer(NULL, 0, 0);
7740 R_Mesh_ResetTextureState();
7741 R_SetupGenericShader(false);
7743 if(rsurface.texture && rsurface.texture->currentskinframe)
7745 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7746 c[3] *= rsurface.texture->currentalpha;
7756 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7758 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7759 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7760 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7763 // brighten it up (as texture value 127 means "unlit")
7764 c[0] *= 2 * r_refdef.view.colorscale;
7765 c[1] *= 2 * r_refdef.view.colorscale;
7766 c[2] *= 2 * r_refdef.view.colorscale;
7768 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7769 c[3] *= r_wateralpha.value;
7771 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7773 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7774 GL_DepthMask(false);
7776 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7778 GL_BlendFunc(GL_ONE, GL_ONE);
7779 GL_DepthMask(false);
7781 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7783 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7784 GL_DepthMask(false);
7786 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7788 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7789 GL_DepthMask(false);
7793 GL_BlendFunc(GL_ONE, GL_ZERO);
7794 GL_DepthMask(writedepth);
7797 rsurface.lightmapcolor4f = NULL;
7799 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7801 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7803 rsurface.lightmapcolor4f = NULL;
7804 rsurface.lightmapcolor4f_bufferobject = 0;
7805 rsurface.lightmapcolor4f_bufferoffset = 0;
7807 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7809 qboolean applycolor = true;
7812 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7814 r_refdef.lightmapintensity = 1;
7815 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7816 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7820 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7822 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7823 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7824 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7827 if(!rsurface.lightmapcolor4f)
7828 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7830 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7831 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7832 if(r_refdef.fogenabled)
7833 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7835 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7836 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7839 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7842 RSurf_SetupDepthAndCulling();
7843 if (r_showsurfaces.integer == 3)
7844 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7845 else if (r_glsl.integer && gl_support_fragment_shader)
7846 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7847 else if (gl_combine.integer && r_textureunits.integer >= 2)
7848 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7850 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7854 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7857 RSurf_SetupDepthAndCulling();
7858 if (r_showsurfaces.integer == 3)
7859 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7860 else if (r_glsl.integer && gl_support_fragment_shader)
7861 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7862 else if (gl_combine.integer && r_textureunits.integer >= 2)
7863 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7865 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7869 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7872 int texturenumsurfaces, endsurface;
7874 const msurface_t *surface;
7875 const msurface_t *texturesurfacelist[1024];
7877 // if the model is static it doesn't matter what value we give for
7878 // wantnormals and wanttangents, so this logic uses only rules applicable
7879 // to a model, knowing that they are meaningless otherwise
7880 if (ent == r_refdef.scene.worldentity)
7881 RSurf_ActiveWorldEntity();
7882 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7883 RSurf_ActiveModelEntity(ent, false, false);
7885 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7887 for (i = 0;i < numsurfaces;i = j)
7890 surface = rsurface.modelsurfaces + surfacelist[i];
7891 texture = surface->texture;
7892 rsurface.texture = R_GetCurrentTexture(texture);
7893 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7894 // scan ahead until we find a different texture
7895 endsurface = min(i + 1024, numsurfaces);
7896 texturenumsurfaces = 0;
7897 texturesurfacelist[texturenumsurfaces++] = surface;
7898 for (;j < endsurface;j++)
7900 surface = rsurface.modelsurfaces + surfacelist[j];
7901 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7903 texturesurfacelist[texturenumsurfaces++] = surface;
7905 // render the range of surfaces
7906 if (ent == r_refdef.scene.worldentity)
7907 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7909 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7911 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7912 GL_AlphaTest(false);
7915 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7917 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7921 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7923 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7925 RSurf_SetupDepthAndCulling();
7926 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7927 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7929 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7931 RSurf_SetupDepthAndCulling();
7932 GL_AlphaTest(false);
7933 R_Mesh_ColorPointer(NULL, 0, 0);
7934 R_Mesh_ResetTextureState();
7935 R_SetupGenericShader(false);
7936 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7938 GL_BlendFunc(GL_ONE, GL_ZERO);
7939 GL_Color(0, 0, 0, 1);
7940 GL_DepthTest(writedepth);
7941 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7943 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7945 RSurf_SetupDepthAndCulling();
7946 GL_AlphaTest(false);
7947 R_Mesh_ColorPointer(NULL, 0, 0);
7948 R_Mesh_ResetTextureState();
7949 R_SetupGenericShader(false);
7950 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7952 GL_BlendFunc(GL_ONE, GL_ZERO);
7954 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7956 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7957 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7958 else if (!rsurface.texture->currentnumlayers)
7960 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7962 // transparent surfaces get pushed off into the transparent queue
7963 int surfacelistindex;
7964 const msurface_t *surface;
7965 vec3_t tempcenter, center;
7966 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7968 surface = texturesurfacelist[surfacelistindex];
7969 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7970 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7971 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7972 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7973 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7978 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7979 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7984 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7988 // break the surface list down into batches by texture and use of lightmapping
7989 for (i = 0;i < numsurfaces;i = j)
7992 // texture is the base texture pointer, rsurface.texture is the
7993 // current frame/skin the texture is directing us to use (for example
7994 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7995 // use skin 1 instead)
7996 texture = surfacelist[i]->texture;
7997 rsurface.texture = R_GetCurrentTexture(texture);
7998 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7999 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8001 // if this texture is not the kind we want, skip ahead to the next one
8002 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8006 // simply scan ahead until we find a different texture or lightmap state
8007 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8009 // render the range of surfaces
8010 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
8014 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
8019 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8021 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8023 RSurf_SetupDepthAndCulling();
8024 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8025 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8027 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8029 RSurf_SetupDepthAndCulling();
8030 GL_AlphaTest(false);
8031 R_Mesh_ColorPointer(NULL, 0, 0);
8032 R_Mesh_ResetTextureState();
8033 R_SetupGenericShader(false);
8034 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8036 GL_BlendFunc(GL_ONE, GL_ZERO);
8037 GL_Color(0, 0, 0, 1);
8038 GL_DepthTest(writedepth);
8039 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8041 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8043 RSurf_SetupDepthAndCulling();
8044 GL_AlphaTest(false);
8045 R_Mesh_ColorPointer(NULL, 0, 0);
8046 R_Mesh_ResetTextureState();
8047 R_SetupGenericShader(false);
8048 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8050 GL_BlendFunc(GL_ONE, GL_ZERO);
8052 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8054 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8055 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8056 else if (!rsurface.texture->currentnumlayers)
8058 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8060 // transparent surfaces get pushed off into the transparent queue
8061 int surfacelistindex;
8062 const msurface_t *surface;
8063 vec3_t tempcenter, center;
8064 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8066 surface = texturesurfacelist[surfacelistindex];
8067 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8068 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8069 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8070 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8071 if (queueentity->transparent_offset) // transparent offset
8073 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8074 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8075 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8077 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8082 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8083 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8088 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8092 // break the surface list down into batches by texture and use of lightmapping
8093 for (i = 0;i < numsurfaces;i = j)
8096 // texture is the base texture pointer, rsurface.texture is the
8097 // current frame/skin the texture is directing us to use (for example
8098 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8099 // use skin 1 instead)
8100 texture = surfacelist[i]->texture;
8101 rsurface.texture = R_GetCurrentTexture(texture);
8102 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8103 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8105 // if this texture is not the kind we want, skip ahead to the next one
8106 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8110 // simply scan ahead until we find a different texture or lightmap state
8111 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8113 // render the range of surfaces
8114 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8118 float locboxvertex3f[6*4*3] =
8120 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8121 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8122 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8123 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8124 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8125 1,0,0, 0,0,0, 0,1,0, 1,1,0
8128 unsigned short locboxelements[6*2*3] =
8138 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8141 cl_locnode_t *loc = (cl_locnode_t *)ent;
8143 float vertex3f[6*4*3];
8145 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8146 GL_DepthMask(false);
8147 GL_DepthRange(0, 1);
8148 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8150 GL_CullFace(GL_NONE);
8151 R_Mesh_Matrix(&identitymatrix);
8153 R_Mesh_VertexPointer(vertex3f, 0, 0);
8154 R_Mesh_ColorPointer(NULL, 0, 0);
8155 R_Mesh_ResetTextureState();
8156 R_SetupGenericShader(false);
8159 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8160 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8161 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8162 surfacelist[0] < 0 ? 0.5f : 0.125f);
8164 if (VectorCompare(loc->mins, loc->maxs))
8166 VectorSet(size, 2, 2, 2);
8167 VectorMA(loc->mins, -0.5f, size, mins);
8171 VectorCopy(loc->mins, mins);
8172 VectorSubtract(loc->maxs, loc->mins, size);
8175 for (i = 0;i < 6*4*3;)
8176 for (j = 0;j < 3;j++, i++)
8177 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8179 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8182 void R_DrawLocs(void)
8185 cl_locnode_t *loc, *nearestloc;
8187 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8188 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8190 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8191 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8195 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8197 if (decalsystem->decals)
8198 Mem_Free(decalsystem->decals);
8199 memset(decalsystem, 0, sizeof(*decalsystem));
8202 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)
8213 // expand or initialize the system
8214 if (decalsystem->maxdecals <= decalsystem->numdecals)
8216 decalsystem_t old = *decalsystem;
8217 qboolean useshortelements;
8218 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8219 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8220 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)));
8221 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8222 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8223 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8224 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8225 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8226 if (decalsystem->numdecals)
8228 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8229 memcpy(decalsystem->vertex3f, old.vertex3f, decalsystem->numdecals * sizeof(float[3][3]));
8230 memcpy(decalsystem->texcoord2f, old.texcoord2f, decalsystem->numdecals * sizeof(float[3][2]));
8231 memcpy(decalsystem->color4f, old.color4f, decalsystem->numdecals * sizeof(float[3][4]));
8233 Mem_Free(old.decals);
8234 for (i = 0;i < decalsystem->maxdecals*3;i++)
8235 decalsystem->element3i[i] = i;
8236 if (useshortelements)
8237 for (i = 0;i < decalsystem->maxdecals*3;i++)
8238 decalsystem->element3s[i] = i;
8241 // grab a decal and search for another free slot for the next one
8242 maxdecals = decalsystem->maxdecals;
8243 decals = decalsystem->decals;
8244 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8245 v3f = decalsystem->vertex3f + 9*i;
8246 tc2f = decalsystem->texcoord2f + 6*i;
8247 c4f = decalsystem->color4f + 12*i;
8248 for (i = decalsystem->freedecal;i < maxdecals && decals[i].colors[0][3];i++)
8250 decalsystem->freedecal = i;
8251 if (decalsystem->numdecals <= i)
8252 decalsystem->numdecals = i + 1;
8254 // initialize the decal
8256 decal->triangleindex = triangleindex;
8257 decal->colors[0][0] = (unsigned char)(c0[0]*255.0f);
8258 decal->colors[0][1] = (unsigned char)(c0[1]*255.0f);
8259 decal->colors[0][2] = (unsigned char)(c0[2]*255.0f);
8260 decal->colors[0][3] = 255;
8261 decal->colors[1][0] = (unsigned char)(c1[0]*255.0f);
8262 decal->colors[1][1] = (unsigned char)(c1[1]*255.0f);
8263 decal->colors[1][2] = (unsigned char)(c1[2]*255.0f);
8264 decal->colors[1][3] = 255;
8265 decal->colors[2][0] = (unsigned char)(c2[0]*255.0f);
8266 decal->colors[2][1] = (unsigned char)(c2[1]*255.0f);
8267 decal->colors[2][2] = (unsigned char)(c2[2]*255.0f);
8268 decal->colors[2][3] = 255;
8285 c4f[ 0] = decal->colors[0][0] * ca;
8286 c4f[ 1] = decal->colors[0][1] * ca;
8287 c4f[ 2] = decal->colors[0][2] * ca;
8289 c4f[ 4] = decal->colors[1][0] * ca;
8290 c4f[ 5] = decal->colors[1][1] * ca;
8291 c4f[ 6] = decal->colors[1][2] * ca;
8293 c4f[ 8] = decal->colors[2][0] * ca;
8294 c4f[ 9] = decal->colors[2][1] * ca;
8295 c4f[10] = decal->colors[2][2] * ca;
8299 extern cvar_t cl_decals_bias;
8300 extern cvar_t cl_decals_models;
8301 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)
8303 matrix4x4_t projection;
8304 decalsystem_t *decalsystem;
8307 const float *vertex3f;
8308 const msurface_t *surface;
8309 const msurface_t *surfaces;
8310 const int *surfacelist;
8311 const texture_t *texture;
8315 int surfacelistindex;
8321 float localorigin[3];
8322 float localnormal[3];
8333 float points[2][9][3];
8337 decalsystem = &ent->decalsystem;
8339 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8341 R_DecalSystem_Reset(&ent->decalsystem);
8345 if (!model->brush.data_nodes && !cl_decals_models.integer)
8347 if (decalsystem->model)
8348 R_DecalSystem_Reset(decalsystem);
8352 if (decalsystem->model != model)
8353 R_DecalSystem_Reset(decalsystem);
8354 decalsystem->model = model;
8356 RSurf_ActiveModelEntity(ent, false, false);
8358 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8359 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8360 VectorNormalize(localnormal);
8361 localsize = worldsize*rsurface.inversematrixscale;
8362 ilocalsize = 1.0f / localsize;
8363 localmins[0] = localorigin[0] - localsize;
8364 localmins[1] = localorigin[1] - localsize;
8365 localmins[2] = localorigin[2] - localsize;
8366 localmaxs[0] = localorigin[0] + localsize;
8367 localmaxs[1] = localorigin[1] + localsize;
8368 localmaxs[2] = localorigin[2] + localsize;
8370 //VectorCopy(localnormal, planes[4]);
8371 //VectorVectors(planes[4], planes[2], planes[0]);
8372 AnglesFromVectors(angles, localnormal, NULL, false);
8373 AngleVectors(angles, planes[0], planes[2], planes[4]);
8374 VectorNegate(planes[0], planes[1]);
8375 VectorNegate(planes[2], planes[3]);
8376 VectorNegate(planes[4], planes[5]);
8377 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8378 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8379 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8380 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8381 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8382 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8387 matrix4x4_t forwardprojection;
8388 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8389 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8394 float projectionvector[4][3];
8395 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8396 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8397 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8398 projectionvector[0][0] = planes[0][0] * ilocalsize;
8399 projectionvector[0][1] = planes[1][0] * ilocalsize;
8400 projectionvector[0][2] = planes[2][0] * ilocalsize;
8401 projectionvector[1][0] = planes[0][1] * ilocalsize;
8402 projectionvector[1][1] = planes[1][1] * ilocalsize;
8403 projectionvector[1][2] = planes[2][1] * ilocalsize;
8404 projectionvector[2][0] = planes[0][2] * ilocalsize;
8405 projectionvector[2][1] = planes[1][2] * ilocalsize;
8406 projectionvector[2][2] = planes[2][2] * ilocalsize;
8407 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8408 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8409 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8410 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8414 dynamic = model->surfmesh.isanimated;
8415 vertex3f = rsurface.modelvertex3f;
8416 numsurfacelist = model->nummodelsurfaces;
8417 surfacelist = model->sortedmodelsurfaces;
8418 surfaces = model->data_surfaces;
8419 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8421 surface = surfaces + surfacelist[surfacelistindex];
8422 // skip transparent surfaces
8423 texture = surface->texture;
8424 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8426 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8428 if (texture->currentalpha < 1)
8430 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8432 numvertices = surface->num_vertices;
8433 numtriangles = surface->num_triangles;
8434 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8436 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8438 index = 3*e[cornerindex];
8439 VectorCopy(vertex3f + index, v[cornerindex]);
8442 //TriangleNormal(v[0], v[1], v[2], normal);
8443 //if (DotProduct(normal, localnormal) < 0.0f)
8445 // clip by each of the box planes formed from the projection matrix
8446 // if anything survives, we emit the decal
8447 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]);
8450 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]);
8453 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]);
8456 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]);
8459 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]);
8462 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]);
8465 // some part of the triangle survived, so we have to accept it...
8468 // dynamic always uses the original triangle
8470 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8472 index = 3*e[cornerindex];
8473 VectorCopy(vertex3f + index, v[cornerindex]);
8476 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8478 // convert vertex positions to texcoords
8479 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8480 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8481 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8482 // calculate distance fade from the projection origin
8483 f = a * (1.0f-fabs(temp[0]));
8485 c[cornerindex][0] = r * f;
8486 c[cornerindex][1] = g * f;
8487 c[cornerindex][2] = b * f;
8488 c[cornerindex][3] = 1.0f;
8489 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8492 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex);
8494 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8495 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);
8500 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)
8502 int renderentityindex;
8505 entity_render_t *ent;
8507 worldmins[0] = worldorigin[0] - worldsize;
8508 worldmins[1] = worldorigin[1] - worldsize;
8509 worldmins[2] = worldorigin[2] - worldsize;
8510 worldmaxs[0] = worldorigin[0] + worldsize;
8511 worldmaxs[1] = worldorigin[1] + worldsize;
8512 worldmaxs[2] = worldorigin[2] + worldsize;
8514 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8516 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8518 ent = r_refdef.scene.entities[renderentityindex];
8519 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8522 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8526 extern skinframe_t *decalskinframe;
8527 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8530 decalsystem_t *decalsystem = &ent->decalsystem;
8541 if (!decalsystem->numdecals)
8544 if (r_showsurfaces.integer)
8547 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8549 R_DecalSystem_Reset(decalsystem);
8553 // if the model is static it doesn't matter what value we give for
8554 // wantnormals and wanttangents, so this logic uses only rules applicable
8555 // to a model, knowing that they are meaningless otherwise
8556 if (ent == r_refdef.scene.worldentity)
8557 RSurf_ActiveWorldEntity();
8559 RSurf_ActiveModelEntity(ent, false, false);
8561 if (decalsystem->lastupdatetime)
8562 frametime = cl.time - decalsystem->lastupdatetime;
8565 decalsystem->lastupdatetime = cl.time;
8566 decal = decalsystem->decals;
8567 numdecals = decalsystem->numdecals;
8569 fadedelay = cl_decals_time.value;
8570 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
8572 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8574 if (!decal->colors[0][3])
8577 decal->lived += frametime;
8578 if (decal->lived >= fadedelay)
8580 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
8583 // kill the decal by zeroing vertex data
8584 memset(decalsystem->vertex3f + 9*i, 0, sizeof(float[3][3]));
8585 memset(decalsystem->texcoord2f + 6*i, 0, sizeof(float[3][2]));
8586 memset(decalsystem->color4f + 12*i, 0, sizeof(float[3][4]));
8587 memset(decal, 0, sizeof(*decal));
8588 if (decalsystem->freedecal > i)
8589 decalsystem->freedecal = i;
8593 // update color values for fading decals
8594 alpha *= (1.0f/255.0f);
8595 c4f = decalsystem->color4f + 12*i;
8596 c4f[ 0] = decal->colors[0][0] * alpha;
8597 c4f[ 1] = decal->colors[0][1] * alpha;
8598 c4f[ 2] = decal->colors[0][2] * alpha;
8600 c4f[ 4] = decal->colors[1][0] * alpha;
8601 c4f[ 5] = decal->colors[1][1] * alpha;
8602 c4f[ 6] = decal->colors[1][2] * alpha;
8604 c4f[ 8] = decal->colors[2][0] * alpha;
8605 c4f[ 9] = decal->colors[2][1] * alpha;
8606 c4f[10] = decal->colors[2][2] * alpha;
8610 // update vertex positions for animated models
8611 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8613 e = rsurface.modelelement3i + 3*decal->triangleindex;
8614 v3f = decalsystem->vertex3f + 9*i;
8615 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8616 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8617 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8621 // reduce numdecals if possible
8622 while (numdecals > 0 && !decalsystem->decals[numdecals - 1].colors[0][3])
8624 decalsystem->numdecals = numdecals;
8628 r_refdef.stats.decals += numdecals;
8629 // now render the decals all at once
8630 // (this assumes they all use one particle font texture!)
8631 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);
8632 R_Mesh_ResetTextureState();
8633 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8634 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8635 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8636 R_SetupGenericShader(true);
8637 GL_DepthMask(false);
8638 GL_DepthRange(0, 1);
8639 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
8641 GL_CullFace(GL_NONE);
8642 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8643 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8644 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8645 GL_LockArrays(0, numdecals * 3);
8646 R_Mesh_Draw(0, numdecals * 3, 0, numdecals, decalsystem->element3i, decalsystem->element3s, 0, 0);
8647 GL_LockArrays(0, 0);
8652 // if there are no decals left, reset decalsystem
8653 R_DecalSystem_Reset(decalsystem);
8657 void R_DrawDebugModel(void)
8659 entity_render_t *ent = rsurface.entity;
8660 int i, j, k, l, flagsmask;
8661 const int *elements;
8663 const msurface_t *surface;
8664 dp_model_t *model = ent->model;
8667 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8669 R_Mesh_ColorPointer(NULL, 0, 0);
8670 R_Mesh_ResetTextureState();
8671 R_SetupGenericShader(false);
8672 GL_DepthRange(0, 1);
8673 GL_DepthTest(!r_showdisabledepthtest.integer);
8674 GL_DepthMask(false);
8675 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8677 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8679 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8680 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8682 if (brush->colbrushf && brush->colbrushf->numtriangles)
8684 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8685 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);
8686 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8689 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8691 if (surface->num_collisiontriangles)
8693 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8694 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);
8695 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8700 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8702 if (r_showtris.integer || r_shownormals.integer)
8704 if (r_showdisabledepthtest.integer)
8706 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8707 GL_DepthMask(false);
8711 GL_BlendFunc(GL_ONE, GL_ZERO);
8714 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8716 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8718 rsurface.texture = R_GetCurrentTexture(surface->texture);
8719 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8721 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8722 if (r_showtris.value > 0)
8724 if (!rsurface.texture->currentlayers->depthmask)
8725 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8726 else if (ent == r_refdef.scene.worldentity)
8727 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8729 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8730 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8731 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8732 R_Mesh_ColorPointer(NULL, 0, 0);
8733 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8734 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8735 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8736 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);
8737 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8740 if (r_shownormals.value < 0)
8743 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8745 VectorCopy(rsurface.vertex3f + l * 3, v);
8746 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8747 qglVertex3f(v[0], v[1], v[2]);
8748 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8749 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8750 qglVertex3f(v[0], v[1], v[2]);
8755 if (r_shownormals.value > 0)
8758 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8760 VectorCopy(rsurface.vertex3f + l * 3, v);
8761 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8762 qglVertex3f(v[0], v[1], v[2]);
8763 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8764 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8765 qglVertex3f(v[0], v[1], v[2]);
8770 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8772 VectorCopy(rsurface.vertex3f + l * 3, v);
8773 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8774 qglVertex3f(v[0], v[1], v[2]);
8775 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8776 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8777 qglVertex3f(v[0], v[1], v[2]);
8782 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8784 VectorCopy(rsurface.vertex3f + l * 3, v);
8785 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8786 qglVertex3f(v[0], v[1], v[2]);
8787 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8788 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8789 qglVertex3f(v[0], v[1], v[2]);
8796 rsurface.texture = NULL;
8800 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8801 int r_maxsurfacelist = 0;
8802 const msurface_t **r_surfacelist = NULL;
8803 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8805 int i, j, endj, f, flagsmask;
8807 dp_model_t *model = r_refdef.scene.worldmodel;
8808 msurface_t *surfaces;
8809 unsigned char *update;
8810 int numsurfacelist = 0;
8814 if (r_maxsurfacelist < model->num_surfaces)
8816 r_maxsurfacelist = model->num_surfaces;
8818 Mem_Free(r_surfacelist);
8819 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8822 RSurf_ActiveWorldEntity();
8824 surfaces = model->data_surfaces;
8825 update = model->brushq1.lightmapupdateflags;
8827 // update light styles on this submodel
8828 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8830 model_brush_lightstyleinfo_t *style;
8831 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8833 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8835 int *list = style->surfacelist;
8836 style->value = r_refdef.scene.lightstylevalue[style->style];
8837 for (j = 0;j < style->numsurfaces;j++)
8838 update[list[j]] = true;
8843 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8848 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8854 rsurface.uselightmaptexture = false;
8855 rsurface.texture = NULL;
8856 rsurface.rtlight = NULL;
8858 // add visible surfaces to draw list
8859 for (i = 0;i < model->nummodelsurfaces;i++)
8861 j = model->sortedmodelsurfaces[i];
8862 if (r_refdef.viewcache.world_surfacevisible[j])
8863 r_surfacelist[numsurfacelist++] = surfaces + j;
8865 // update lightmaps if needed
8867 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8868 if (r_refdef.viewcache.world_surfacevisible[j])
8870 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8871 // don't do anything if there were no surfaces
8872 if (!numsurfacelist)
8874 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8877 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8878 GL_AlphaTest(false);
8880 // add to stats if desired
8881 if (r_speeds.integer && !skysurfaces && !depthonly)
8883 r_refdef.stats.world_surfaces += numsurfacelist;
8884 for (j = 0;j < numsurfacelist;j++)
8885 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8888 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8891 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8893 int i, j, endj, f, flagsmask;
8895 dp_model_t *model = ent->model;
8896 msurface_t *surfaces;
8897 unsigned char *update;
8898 int numsurfacelist = 0;
8902 if (r_maxsurfacelist < model->num_surfaces)
8904 r_maxsurfacelist = model->num_surfaces;
8906 Mem_Free(r_surfacelist);
8907 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8910 // if the model is static it doesn't matter what value we give for
8911 // wantnormals and wanttangents, so this logic uses only rules applicable
8912 // to a model, knowing that they are meaningless otherwise
8913 if (ent == r_refdef.scene.worldentity)
8914 RSurf_ActiveWorldEntity();
8915 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8916 RSurf_ActiveModelEntity(ent, false, false);
8918 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8920 surfaces = model->data_surfaces;
8921 update = model->brushq1.lightmapupdateflags;
8923 // update light styles
8924 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8926 model_brush_lightstyleinfo_t *style;
8927 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8929 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8931 int *list = style->surfacelist;
8932 style->value = r_refdef.scene.lightstylevalue[style->style];
8933 for (j = 0;j < style->numsurfaces;j++)
8934 update[list[j]] = true;
8939 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8944 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8950 rsurface.uselightmaptexture = false;
8951 rsurface.texture = NULL;
8952 rsurface.rtlight = NULL;
8954 // add visible surfaces to draw list
8955 for (i = 0;i < model->nummodelsurfaces;i++)
8956 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8957 // don't do anything if there were no surfaces
8958 if (!numsurfacelist)
8960 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8963 // update lightmaps if needed
8965 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8967 R_BuildLightMap(ent, surfaces + j);
8968 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8969 GL_AlphaTest(false);
8971 // add to stats if desired
8972 if (r_speeds.integer && !skysurfaces && !depthonly)
8974 r_refdef.stats.entities_surfaces += numsurfacelist;
8975 for (j = 0;j < numsurfacelist;j++)
8976 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8979 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8982 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
8984 static texture_t texture;
8985 static msurface_t surface;
8986 const msurface_t *surfacelist = &surface;
8988 // fake enough texture and surface state to render this geometry
8990 texture.update_lastrenderframe = -1; // regenerate this texture
8991 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
8992 texture.currentskinframe = skinframe;
8993 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
8994 texture.specularscalemod = 1;
8995 texture.specularpowermod = 1;
8997 surface.texture = &texture;
8998 surface.num_triangles = numtriangles;
8999 surface.num_firsttriangle = firsttriangle;
9000 surface.num_vertices = numvertices;
9001 surface.num_firstvertex = firstvertex;
9004 rsurface.texture = R_GetCurrentTexture(surface.texture);
9005 rsurface.uselightmaptexture = false;
9006 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);