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 #ifdef VIEWCACHEDYNAMIC
2860 if (r_refdef.viewcache.entityvisible)
2861 Mem_Free(r_refdef.viewcache.entityvisible);
2862 if (r_refdef.viewcache.world_pvsbits)
2863 Mem_Free(r_refdef.viewcache.world_pvsbits);
2864 if (r_refdef.viewcache.world_leafvisible)
2865 Mem_Free(r_refdef.viewcache.world_leafvisible);
2866 if (r_refdef.viewcache.world_surfacevisible)
2867 Mem_Free(r_refdef.viewcache.world_surfacevisible);
2868 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2872 void R_Main_AllocViewCache(void)
2874 #ifdef VIEWCACHEDYNAMIC
2875 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
2876 r_refdef.viewcache.maxentities = r_refdef.scene.maxentities;
2877 if (r_refdef.viewcache.maxentities)
2878 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
2881 r_refdef.viewcache.world_numclusters = cl.worldmodel->brush.num_pvsclusters;
2882 r_refdef.viewcache.world_numleafs = cl.worldmodel->brush.num_leafs;
2883 r_refdef.viewcache.world_numsurfaces = cl.worldmodel->num_surfaces;
2884 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, (r_refdef.viewcache.world_numclusters+7)>>3);
2885 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
2886 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
2891 void gl_main_start(void)
2893 R_Main_AllocViewCache();
2897 memset(r_queries, 0, sizeof(r_queries));
2899 r_qwskincache = NULL;
2900 r_qwskincache_size = 0;
2902 // set up r_skinframe loading system for textures
2903 memset(&r_skinframe, 0, sizeof(r_skinframe));
2904 r_skinframe.loadsequence = 1;
2905 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2907 r_main_texturepool = R_AllocTexturePool();
2908 R_BuildBlankTextures();
2910 if (gl_texturecubemap)
2913 R_BuildNormalizationCube();
2915 r_texture_fogattenuation = NULL;
2916 r_texture_gammaramps = NULL;
2917 //r_texture_fogintensity = NULL;
2918 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2919 memset(&r_waterstate, 0, sizeof(r_waterstate));
2920 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2921 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2922 memset(&r_svbsp, 0, sizeof (r_svbsp));
2924 r_refdef.fogmasktable_density = 0;
2927 extern rtexture_t *loadingscreentexture;
2928 void gl_main_shutdown(void)
2930 R_Main_FreeViewCache();
2933 qglDeleteQueriesARB(r_maxqueries, r_queries);
2937 memset(r_queries, 0, sizeof(r_queries));
2939 r_qwskincache = NULL;
2940 r_qwskincache_size = 0;
2942 // clear out the r_skinframe state
2943 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2944 memset(&r_skinframe, 0, sizeof(r_skinframe));
2947 Mem_Free(r_svbsp.nodes);
2948 memset(&r_svbsp, 0, sizeof (r_svbsp));
2949 R_FreeTexturePool(&r_main_texturepool);
2950 loadingscreentexture = NULL;
2951 r_texture_blanknormalmap = NULL;
2952 r_texture_white = NULL;
2953 r_texture_grey128 = NULL;
2954 r_texture_black = NULL;
2955 r_texture_whitecube = NULL;
2956 r_texture_normalizationcube = NULL;
2957 r_texture_fogattenuation = NULL;
2958 r_texture_gammaramps = NULL;
2959 //r_texture_fogintensity = NULL;
2960 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2961 memset(&r_waterstate, 0, sizeof(r_waterstate));
2965 extern void CL_ParseEntityLump(char *entitystring);
2966 void gl_main_newmap(void)
2968 // FIXME: move this code to client
2970 char *entities, entname[MAX_QPATH];
2972 Mem_Free(r_qwskincache);
2973 r_qwskincache = NULL;
2974 r_qwskincache_size = 0;
2977 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2978 l = (int)strlen(entname) - 4;
2979 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2981 memcpy(entname + l, ".ent", 5);
2982 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2984 CL_ParseEntityLump(entities);
2989 if (cl.worldmodel->brush.entities)
2990 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2992 R_Main_FreeViewCache();
2993 R_Main_AllocViewCache();
2996 void GL_Main_Init(void)
2998 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3000 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3001 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3002 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3003 if (gamemode == GAME_NEHAHRA)
3005 Cvar_RegisterVariable (&gl_fogenable);
3006 Cvar_RegisterVariable (&gl_fogdensity);
3007 Cvar_RegisterVariable (&gl_fogred);
3008 Cvar_RegisterVariable (&gl_foggreen);
3009 Cvar_RegisterVariable (&gl_fogblue);
3010 Cvar_RegisterVariable (&gl_fogstart);
3011 Cvar_RegisterVariable (&gl_fogend);
3012 Cvar_RegisterVariable (&gl_skyclip);
3014 Cvar_RegisterVariable(&r_motionblur);
3015 Cvar_RegisterVariable(&r_motionblur_maxblur);
3016 Cvar_RegisterVariable(&r_motionblur_bmin);
3017 Cvar_RegisterVariable(&r_motionblur_vmin);
3018 Cvar_RegisterVariable(&r_motionblur_vmax);
3019 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3020 Cvar_RegisterVariable(&r_motionblur_randomize);
3021 Cvar_RegisterVariable(&r_damageblur);
3022 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3023 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3024 Cvar_RegisterVariable(&r_equalize_entities_by);
3025 Cvar_RegisterVariable(&r_equalize_entities_to);
3026 Cvar_RegisterVariable(&r_animcache);
3027 Cvar_RegisterVariable(&r_depthfirst);
3028 Cvar_RegisterVariable(&r_useinfinitefarclip);
3029 Cvar_RegisterVariable(&r_farclip_base);
3030 Cvar_RegisterVariable(&r_farclip_world);
3031 Cvar_RegisterVariable(&r_nearclip);
3032 Cvar_RegisterVariable(&r_showbboxes);
3033 Cvar_RegisterVariable(&r_showsurfaces);
3034 Cvar_RegisterVariable(&r_showtris);
3035 Cvar_RegisterVariable(&r_shownormals);
3036 Cvar_RegisterVariable(&r_showlighting);
3037 Cvar_RegisterVariable(&r_showshadowvolumes);
3038 Cvar_RegisterVariable(&r_showcollisionbrushes);
3039 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3040 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3041 Cvar_RegisterVariable(&r_showdisabledepthtest);
3042 Cvar_RegisterVariable(&r_drawportals);
3043 Cvar_RegisterVariable(&r_drawentities);
3044 Cvar_RegisterVariable(&r_cullentities_trace);
3045 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3046 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3047 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3048 Cvar_RegisterVariable(&r_drawviewmodel);
3049 Cvar_RegisterVariable(&r_speeds);
3050 Cvar_RegisterVariable(&r_fullbrights);
3051 Cvar_RegisterVariable(&r_wateralpha);
3052 Cvar_RegisterVariable(&r_dynamic);
3053 Cvar_RegisterVariable(&r_fullbright);
3054 Cvar_RegisterVariable(&r_shadows);
3055 Cvar_RegisterVariable(&r_shadows_darken);
3056 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3057 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3058 Cvar_RegisterVariable(&r_shadows_throwdistance);
3059 Cvar_RegisterVariable(&r_shadows_throwdirection);
3060 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3061 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3062 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3063 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3064 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3065 Cvar_RegisterVariable(&r_fog_exp2);
3066 Cvar_RegisterVariable(&r_drawfog);
3067 Cvar_RegisterVariable(&r_textureunits);
3068 Cvar_RegisterVariable(&r_glsl);
3069 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3070 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3071 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3072 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3073 Cvar_RegisterVariable(&r_glsl_postprocess);
3074 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3075 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3076 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3077 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3078 Cvar_RegisterVariable(&r_glsl_usegeneric);
3079 Cvar_RegisterVariable(&r_water);
3080 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3081 Cvar_RegisterVariable(&r_water_clippingplanebias);
3082 Cvar_RegisterVariable(&r_water_refractdistort);
3083 Cvar_RegisterVariable(&r_water_reflectdistort);
3084 Cvar_RegisterVariable(&r_lerpsprites);
3085 Cvar_RegisterVariable(&r_lerpmodels);
3086 Cvar_RegisterVariable(&r_lerplightstyles);
3087 Cvar_RegisterVariable(&r_waterscroll);
3088 Cvar_RegisterVariable(&r_bloom);
3089 Cvar_RegisterVariable(&r_bloom_colorscale);
3090 Cvar_RegisterVariable(&r_bloom_brighten);
3091 Cvar_RegisterVariable(&r_bloom_blur);
3092 Cvar_RegisterVariable(&r_bloom_resolution);
3093 Cvar_RegisterVariable(&r_bloom_colorexponent);
3094 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3095 Cvar_RegisterVariable(&r_hdr);
3096 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3097 Cvar_RegisterVariable(&r_hdr_glowintensity);
3098 Cvar_RegisterVariable(&r_hdr_range);
3099 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3100 Cvar_RegisterVariable(&developer_texturelogging);
3101 Cvar_RegisterVariable(&gl_lightmaps);
3102 Cvar_RegisterVariable(&r_test);
3103 Cvar_RegisterVariable(&r_batchmode);
3104 Cvar_RegisterVariable(&r_glsl_saturation);
3105 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3106 Cvar_SetValue("r_fullbrights", 0);
3107 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3109 Cvar_RegisterVariable(&r_track_sprites);
3110 Cvar_RegisterVariable(&r_track_sprites_flags);
3111 Cvar_RegisterVariable(&r_track_sprites_scalew);
3112 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3115 extern void R_Textures_Init(void);
3116 extern void GL_Draw_Init(void);
3117 extern void GL_Main_Init(void);
3118 extern void R_Shadow_Init(void);
3119 extern void R_Sky_Init(void);
3120 extern void GL_Surf_Init(void);
3121 extern void R_Particles_Init(void);
3122 extern void R_Explosion_Init(void);
3123 extern void gl_backend_init(void);
3124 extern void Sbar_Init(void);
3125 extern void R_LightningBeams_Init(void);
3126 extern void Mod_RenderInit(void);
3128 void Render_Init(void)
3140 R_LightningBeams_Init();
3149 extern char *ENGINE_EXTENSIONS;
3152 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3153 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3154 gl_version = (const char *)qglGetString(GL_VERSION);
3155 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3159 if (!gl_platformextensions)
3160 gl_platformextensions = "";
3162 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3163 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3164 Con_Printf("GL_VERSION: %s\n", gl_version);
3165 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3166 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3168 VID_CheckExtensions();
3170 // LordHavoc: report supported extensions
3171 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3173 // clear to black (loading plaque will be seen over this)
3175 qglClearColor(0,0,0,1);CHECKGLERROR
3176 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3179 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3183 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3185 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3188 p = r_refdef.view.frustum + i;
3193 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3197 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3201 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3205 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3209 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3213 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3217 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3221 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3229 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3233 for (i = 0;i < numplanes;i++)
3240 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3244 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3248 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3252 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3256 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3260 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3264 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3268 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3276 //==================================================================================
3278 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3281 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3282 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3283 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3286 typedef struct r_animcache_entity_s
3293 qboolean wantnormals;
3294 qboolean wanttangents;
3296 r_animcache_entity_t;
3298 typedef struct r_animcache_s
3300 r_animcache_entity_t entity[MAX_EDICTS];
3306 static r_animcache_t r_animcachestate;
3308 void R_AnimCache_Free(void)
3311 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3313 r_animcachestate.entity[idx].maxvertices = 0;
3314 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3315 r_animcachestate.entity[idx].vertex3f = NULL;
3316 r_animcachestate.entity[idx].normal3f = NULL;
3317 r_animcachestate.entity[idx].svector3f = NULL;
3318 r_animcachestate.entity[idx].tvector3f = NULL;
3320 r_animcachestate.currentindex = 0;
3321 r_animcachestate.maxindex = 0;
3324 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3328 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3330 if (cache->maxvertices >= numvertices)
3333 // Release existing memory
3334 if (cache->vertex3f)
3335 Mem_Free(cache->vertex3f);
3337 // Pad by 1024 verts
3338 cache->maxvertices = (numvertices + 1023) & ~1023;
3339 arraySize = cache->maxvertices * 3;
3341 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3342 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3343 r_animcachestate.entity[cacheIdx].vertex3f = base;
3344 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3345 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3346 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3348 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3351 void R_AnimCache_NewFrame(void)
3355 if (r_animcache.integer && r_drawentities.integer)
3356 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3357 else if (r_animcachestate.maxindex)
3360 r_animcachestate.currentindex = 0;
3362 for (i = 0;i < r_refdef.scene.numentities;i++)
3363 r_refdef.scene.entities[i]->animcacheindex = -1;
3366 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3368 dp_model_t *model = ent->model;
3369 r_animcache_entity_t *c;
3370 // see if it's already cached this frame
3371 if (ent->animcacheindex >= 0)
3373 // add normals/tangents if needed
3374 c = r_animcachestate.entity + ent->animcacheindex;
3376 wantnormals = false;
3377 if (c->wanttangents)
3378 wanttangents = false;
3379 if (wantnormals || wanttangents)
3380 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3384 // see if this ent is worth caching
3385 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3387 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3389 // assign it a cache entry and make sure the arrays are big enough
3390 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3391 ent->animcacheindex = r_animcachestate.currentindex++;
3392 c = r_animcachestate.entity + ent->animcacheindex;
3393 c->wantnormals = wantnormals;
3394 c->wanttangents = wanttangents;
3395 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3400 void R_AnimCache_CacheVisibleEntities(void)
3403 qboolean wantnormals;
3404 qboolean wanttangents;
3406 if (!r_animcachestate.maxindex)
3409 wantnormals = !r_showsurfaces.integer;
3410 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3412 // TODO: thread this?
3414 for (i = 0;i < r_refdef.scene.numentities;i++)
3416 if (!r_refdef.viewcache.entityvisible[i])
3418 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3422 //==================================================================================
3424 static void R_View_UpdateEntityLighting (void)
3427 entity_render_t *ent;
3428 vec3_t tempdiffusenormal, avg;
3429 vec_t f, fa, fd, fdd;
3431 for (i = 0;i < r_refdef.scene.numentities;i++)
3433 ent = r_refdef.scene.entities[i];
3435 // skip unseen models
3436 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3440 if (ent->model && ent->model->brush.num_leafs)
3442 // TODO: use modellight for r_ambient settings on world?
3443 VectorSet(ent->modellight_ambient, 0, 0, 0);
3444 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3445 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3449 // fetch the lighting from the worldmodel data
3450 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));
3451 VectorClear(ent->modellight_diffuse);
3452 VectorClear(tempdiffusenormal);
3453 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3456 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3457 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3458 if(ent->flags & RENDER_EQUALIZE)
3460 // first fix up ambient lighting...
3461 if(r_equalize_entities_minambient.value > 0)
3463 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3466 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3467 if(fa < r_equalize_entities_minambient.value * fd)
3470 // fa'/fd' = minambient
3471 // fa'+0.25*fd' = fa+0.25*fd
3473 // fa' = fd' * minambient
3474 // fd'*(0.25+minambient) = fa+0.25*fd
3476 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3477 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3479 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3480 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
3481 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3482 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3487 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3489 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3490 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3493 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3494 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3495 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3501 VectorSet(ent->modellight_ambient, 1, 1, 1);
3503 // move the light direction into modelspace coordinates for lighting code
3504 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3505 if(VectorLength2(ent->modellight_lightdir) == 0)
3506 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3507 VectorNormalize(ent->modellight_lightdir);
3511 #define MAX_LINEOFSIGHTTRACES 64
3513 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3516 vec3_t boxmins, boxmaxs;
3519 dp_model_t *model = r_refdef.scene.worldmodel;
3521 if (!model || !model->brush.TraceLineOfSight)
3524 // expand the box a little
3525 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3526 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3527 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3528 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3529 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3530 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3533 VectorCopy(eye, start);
3534 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3535 if (model->brush.TraceLineOfSight(model, start, end))
3538 // try various random positions
3539 for (i = 0;i < numsamples;i++)
3541 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3542 if (model->brush.TraceLineOfSight(model, start, end))
3550 static void R_View_UpdateEntityVisible (void)
3553 entity_render_t *ent;
3555 if (!r_drawentities.integer)
3558 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3559 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3561 // worldmodel can check visibility
3562 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3563 for (i = 0;i < r_refdef.scene.numentities;i++)
3565 ent = r_refdef.scene.entities[i];
3566 if (!(ent->flags & renderimask))
3567 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)))
3568 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))
3569 r_refdef.viewcache.entityvisible[i] = true;
3571 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3573 for (i = 0;i < r_refdef.scene.numentities;i++)
3575 ent = r_refdef.scene.entities[i];
3576 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3578 if(R_CanSeeBox(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3579 ent->last_trace_visibility = realtime;
3580 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3581 r_refdef.viewcache.entityvisible[i] = 0;
3588 // no worldmodel or it can't check visibility
3589 for (i = 0;i < r_refdef.scene.numentities;i++)
3591 ent = r_refdef.scene.entities[i];
3592 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));
3597 /// only used if skyrendermasked, and normally returns false
3598 int R_DrawBrushModelsSky (void)
3601 entity_render_t *ent;
3603 if (!r_drawentities.integer)
3607 for (i = 0;i < r_refdef.scene.numentities;i++)
3609 if (!r_refdef.viewcache.entityvisible[i])
3611 ent = r_refdef.scene.entities[i];
3612 if (!ent->model || !ent->model->DrawSky)
3614 ent->model->DrawSky(ent);
3620 static void R_DrawNoModel(entity_render_t *ent);
3621 static void R_DrawModels(void)
3624 entity_render_t *ent;
3626 if (!r_drawentities.integer)
3629 for (i = 0;i < r_refdef.scene.numentities;i++)
3631 if (!r_refdef.viewcache.entityvisible[i])
3633 ent = r_refdef.scene.entities[i];
3634 r_refdef.stats.entities++;
3635 if (ent->model && ent->model->Draw != NULL)
3636 ent->model->Draw(ent);
3642 static void R_DrawModelsDepth(void)
3645 entity_render_t *ent;
3647 if (!r_drawentities.integer)
3650 for (i = 0;i < r_refdef.scene.numentities;i++)
3652 if (!r_refdef.viewcache.entityvisible[i])
3654 ent = r_refdef.scene.entities[i];
3655 if (ent->model && ent->model->DrawDepth != NULL)
3656 ent->model->DrawDepth(ent);
3660 static void R_DrawModelsDebug(void)
3663 entity_render_t *ent;
3665 if (!r_drawentities.integer)
3668 for (i = 0;i < r_refdef.scene.numentities;i++)
3670 if (!r_refdef.viewcache.entityvisible[i])
3672 ent = r_refdef.scene.entities[i];
3673 if (ent->model && ent->model->DrawDebug != NULL)
3674 ent->model->DrawDebug(ent);
3678 static void R_DrawModelsAddWaterPlanes(void)
3681 entity_render_t *ent;
3683 if (!r_drawentities.integer)
3686 for (i = 0;i < r_refdef.scene.numentities;i++)
3688 if (!r_refdef.viewcache.entityvisible[i])
3690 ent = r_refdef.scene.entities[i];
3691 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3692 ent->model->DrawAddWaterPlanes(ent);
3696 static void R_DrawModelDecals_Entity(entity_render_t *ent);
3697 static void R_DrawModelDecals(void)
3700 entity_render_t *ent;
3702 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
3704 if (!r_drawentities.integer || r_showsurfaces.integer)
3707 for (i = 0;i < r_refdef.scene.numentities;i++)
3709 if (!r_refdef.viewcache.entityvisible[i])
3711 ent = r_refdef.scene.entities[i];
3712 r_refdef.stats.entities++;
3713 if (ent->decalsystem.numdecals)
3714 R_DrawModelDecals_Entity(ent);
3718 static void R_View_SetFrustum(void)
3721 double slopex, slopey;
3722 vec3_t forward, left, up, origin;
3724 // we can't trust r_refdef.view.forward and friends in reflected scenes
3725 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3728 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3729 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3730 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3731 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3732 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3733 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3734 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3735 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3736 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3737 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3738 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3739 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3743 zNear = r_refdef.nearclip;
3744 nudge = 1.0 - 1.0 / (1<<23);
3745 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3746 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3747 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3748 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3749 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3750 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3751 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3752 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3758 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3759 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3760 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3761 r_refdef.view.frustum[0].dist = m[15] - m[12];
3763 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3764 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3765 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3766 r_refdef.view.frustum[1].dist = m[15] + m[12];
3768 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3769 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3770 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3771 r_refdef.view.frustum[2].dist = m[15] - m[13];
3773 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3774 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3775 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3776 r_refdef.view.frustum[3].dist = m[15] + m[13];
3778 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3779 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3780 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3781 r_refdef.view.frustum[4].dist = m[15] - m[14];
3783 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3784 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3785 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3786 r_refdef.view.frustum[5].dist = m[15] + m[14];
3789 if (r_refdef.view.useperspective)
3791 slopex = 1.0 / r_refdef.view.frustum_x;
3792 slopey = 1.0 / r_refdef.view.frustum_y;
3793 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3794 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3795 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3796 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3797 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3799 // Leaving those out was a mistake, those were in the old code, and they
3800 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3801 // I couldn't reproduce it after adding those normalizations. --blub
3802 VectorNormalize(r_refdef.view.frustum[0].normal);
3803 VectorNormalize(r_refdef.view.frustum[1].normal);
3804 VectorNormalize(r_refdef.view.frustum[2].normal);
3805 VectorNormalize(r_refdef.view.frustum[3].normal);
3807 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3808 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
3809 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
3810 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, 1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
3811 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]);
3813 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3814 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3815 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3816 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3817 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3821 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3822 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3823 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3824 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3825 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3826 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3827 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3828 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3829 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3830 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3832 r_refdef.view.numfrustumplanes = 5;
3834 if (r_refdef.view.useclipplane)
3836 r_refdef.view.numfrustumplanes = 6;
3837 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3840 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3841 PlaneClassify(r_refdef.view.frustum + i);
3843 // LordHavoc: note to all quake engine coders, Quake had a special case
3844 // for 90 degrees which assumed a square view (wrong), so I removed it,
3845 // Quake2 has it disabled as well.
3847 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3848 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3849 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3850 //PlaneClassify(&frustum[0]);
3852 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3853 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3854 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3855 //PlaneClassify(&frustum[1]);
3857 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3858 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3859 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3860 //PlaneClassify(&frustum[2]);
3862 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3863 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3864 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3865 //PlaneClassify(&frustum[3]);
3868 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3869 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3870 //PlaneClassify(&frustum[4]);
3873 void R_View_Update(void)
3875 R_View_SetFrustum();
3876 R_View_WorldVisibility(r_refdef.view.useclipplane);
3877 R_View_UpdateEntityVisible();
3878 R_View_UpdateEntityLighting();
3881 void R_SetupView(qboolean allowwaterclippingplane)
3883 const double *customclipplane = NULL;
3885 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3887 // LordHavoc: couldn't figure out how to make this approach the
3888 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3889 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3890 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3891 dist = r_refdef.view.clipplane.dist;
3892 plane[0] = r_refdef.view.clipplane.normal[0];
3893 plane[1] = r_refdef.view.clipplane.normal[1];
3894 plane[2] = r_refdef.view.clipplane.normal[2];
3896 customclipplane = plane;
3899 if (!r_refdef.view.useperspective)
3900 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
3901 else if (gl_stencil && r_useinfinitefarclip.integer)
3902 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
3904 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
3905 R_SetViewport(&r_refdef.view.viewport);
3908 void R_ResetViewRendering2D(void)
3910 r_viewport_t viewport;
3913 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3914 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
3915 R_SetViewport(&viewport);
3916 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3917 GL_Color(1, 1, 1, 1);
3918 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3919 GL_BlendFunc(GL_ONE, GL_ZERO);
3920 GL_AlphaTest(false);
3921 GL_ScissorTest(false);
3922 GL_DepthMask(false);
3923 GL_DepthRange(0, 1);
3924 GL_DepthTest(false);
3925 R_Mesh_Matrix(&identitymatrix);
3926 R_Mesh_ResetTextureState();
3927 GL_PolygonOffset(0, 0);
3928 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3929 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3930 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3931 qglStencilMask(~0);CHECKGLERROR
3932 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3933 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3934 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3935 R_SetupGenericShader(true);
3938 void R_ResetViewRendering3D(void)
3943 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3944 GL_Color(1, 1, 1, 1);
3945 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3946 GL_BlendFunc(GL_ONE, GL_ZERO);
3947 GL_AlphaTest(false);
3948 GL_ScissorTest(true);
3950 GL_DepthRange(0, 1);
3952 R_Mesh_Matrix(&identitymatrix);
3953 R_Mesh_ResetTextureState();
3954 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3955 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3956 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3957 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3958 qglStencilMask(~0);CHECKGLERROR
3959 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3960 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3961 GL_CullFace(r_refdef.view.cullface_back);
3962 R_SetupGenericShader(true);
3965 void R_RenderScene(void);
3966 void R_RenderWaterPlanes(void);
3968 static void R_Water_StartFrame(void)
3971 int waterwidth, waterheight, texturewidth, textureheight;
3972 r_waterstate_waterplane_t *p;
3974 // set waterwidth and waterheight to the water resolution that will be
3975 // used (often less than the screen resolution for faster rendering)
3976 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3977 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3979 // calculate desired texture sizes
3980 // can't use water if the card does not support the texture size
3981 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3982 texturewidth = textureheight = waterwidth = waterheight = 0;
3983 else if (gl_support_arb_texture_non_power_of_two)
3985 texturewidth = waterwidth;
3986 textureheight = waterheight;
3990 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3991 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3994 // allocate textures as needed
3995 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3997 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3998 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4000 if (p->texture_refraction)
4001 R_FreeTexture(p->texture_refraction);
4002 p->texture_refraction = NULL;
4003 if (p->texture_reflection)
4004 R_FreeTexture(p->texture_reflection);
4005 p->texture_reflection = NULL;
4007 memset(&r_waterstate, 0, sizeof(r_waterstate));
4008 r_waterstate.texturewidth = texturewidth;
4009 r_waterstate.textureheight = textureheight;
4012 if (r_waterstate.texturewidth)
4014 r_waterstate.enabled = true;
4016 // when doing a reduced render (HDR) we want to use a smaller area
4017 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4018 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4020 // set up variables that will be used in shader setup
4021 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4022 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4023 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4024 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4027 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4028 r_waterstate.numwaterplanes = 0;
4031 void R_Water_AddWaterPlane(msurface_t *surface)
4033 int triangleindex, planeindex;
4039 r_waterstate_waterplane_t *p;
4040 texture_t *t = R_GetCurrentTexture(surface->texture);
4041 // just use the first triangle with a valid normal for any decisions
4042 VectorClear(normal);
4043 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4045 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4046 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4047 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4048 TriangleNormal(vert[0], vert[1], vert[2], normal);
4049 if (VectorLength2(normal) >= 0.001)
4053 VectorCopy(normal, plane.normal);
4054 VectorNormalize(plane.normal);
4055 plane.dist = DotProduct(vert[0], plane.normal);
4056 PlaneClassify(&plane);
4057 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4059 // skip backfaces (except if nocullface is set)
4060 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4062 VectorNegate(plane.normal, plane.normal);
4064 PlaneClassify(&plane);
4068 // find a matching plane if there is one
4069 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4070 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4072 if (planeindex >= r_waterstate.maxwaterplanes)
4073 return; // nothing we can do, out of planes
4075 // if this triangle does not fit any known plane rendered this frame, add one
4076 if (planeindex >= r_waterstate.numwaterplanes)
4078 // store the new plane
4079 r_waterstate.numwaterplanes++;
4081 // clear materialflags and pvs
4082 p->materialflags = 0;
4083 p->pvsvalid = false;
4085 // merge this surface's materialflags into the waterplane
4086 p->materialflags |= t->currentmaterialflags;
4087 // merge this surface's PVS into the waterplane
4088 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4089 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4090 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4092 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4097 static void R_Water_ProcessPlanes(void)
4099 r_refdef_view_t originalview;
4100 r_refdef_view_t myview;
4102 r_waterstate_waterplane_t *p;
4104 originalview = r_refdef.view;
4106 // make sure enough textures are allocated
4107 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4109 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4111 if (!p->texture_refraction)
4112 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
4113 if (!p->texture_refraction)
4117 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4119 if (!p->texture_reflection)
4120 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
4121 if (!p->texture_reflection)
4127 r_refdef.view = originalview;
4128 r_refdef.view.showdebug = false;
4129 r_refdef.view.width = r_waterstate.waterwidth;
4130 r_refdef.view.height = r_waterstate.waterheight;
4131 r_refdef.view.useclipplane = true;
4132 myview = r_refdef.view;
4133 r_waterstate.renderingscene = true;
4134 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4136 // render the normal view scene and copy into texture
4137 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
4138 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4140 r_refdef.view = myview;
4141 r_refdef.view.clipplane = p->plane;
4142 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4143 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4144 PlaneClassify(&r_refdef.view.clipplane);
4146 R_ResetViewRendering3D();
4147 R_ClearScreen(r_refdef.fogenabled);
4151 // copy view into the screen texture
4152 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4153 GL_ActiveTexture(0);
4155 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4158 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4160 r_refdef.view = myview;
4161 // render reflected scene and copy into texture
4162 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4163 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4164 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4165 r_refdef.view.clipplane = p->plane;
4166 // reverse the cullface settings for this render
4167 r_refdef.view.cullface_front = GL_FRONT;
4168 r_refdef.view.cullface_back = GL_BACK;
4169 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4171 r_refdef.view.usecustompvs = true;
4173 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4175 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4178 R_ResetViewRendering3D();
4179 R_ClearScreen(r_refdef.fogenabled);
4183 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4184 GL_ActiveTexture(0);
4186 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4189 r_waterstate.renderingscene = false;
4190 r_refdef.view = originalview;
4191 R_ResetViewRendering3D();
4192 R_ClearScreen(r_refdef.fogenabled);
4196 r_refdef.view = originalview;
4197 r_waterstate.renderingscene = false;
4198 Cvar_SetValueQuick(&r_water, 0);
4199 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4203 void R_Bloom_StartFrame(void)
4205 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4207 // set bloomwidth and bloomheight to the bloom resolution that will be
4208 // used (often less than the screen resolution for faster rendering)
4209 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4210 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4211 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4212 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
4213 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
4215 // calculate desired texture sizes
4216 if (gl_support_arb_texture_non_power_of_two)
4218 screentexturewidth = r_refdef.view.width;
4219 screentextureheight = r_refdef.view.height;
4220 bloomtexturewidth = r_bloomstate.bloomwidth;
4221 bloomtextureheight = r_bloomstate.bloomheight;
4225 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4226 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4227 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4228 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4231 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
4233 Cvar_SetValueQuick(&r_hdr, 0);
4234 Cvar_SetValueQuick(&r_bloom, 0);
4235 Cvar_SetValueQuick(&r_motionblur, 0);
4236 Cvar_SetValueQuick(&r_damageblur, 0);
4239 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
4240 screentexturewidth = screentextureheight = 0;
4241 if (!r_hdr.integer && !r_bloom.integer)
4242 bloomtexturewidth = bloomtextureheight = 0;
4244 // allocate textures as needed
4245 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4247 if (r_bloomstate.texture_screen)
4248 R_FreeTexture(r_bloomstate.texture_screen);
4249 r_bloomstate.texture_screen = NULL;
4250 r_bloomstate.screentexturewidth = screentexturewidth;
4251 r_bloomstate.screentextureheight = screentextureheight;
4252 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4253 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
4255 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4257 if (r_bloomstate.texture_bloom)
4258 R_FreeTexture(r_bloomstate.texture_bloom);
4259 r_bloomstate.texture_bloom = NULL;
4260 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4261 r_bloomstate.bloomtextureheight = bloomtextureheight;
4262 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4263 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
4266 // when doing a reduced render (HDR) we want to use a smaller area
4267 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4268 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4269 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4270 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4271 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4273 // set up a texcoord array for the full resolution screen image
4274 // (we have to keep this around to copy back during final render)
4275 r_bloomstate.screentexcoord2f[0] = 0;
4276 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4277 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4278 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4279 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4280 r_bloomstate.screentexcoord2f[5] = 0;
4281 r_bloomstate.screentexcoord2f[6] = 0;
4282 r_bloomstate.screentexcoord2f[7] = 0;
4284 // set up a texcoord array for the reduced resolution bloom image
4285 // (which will be additive blended over the screen image)
4286 r_bloomstate.bloomtexcoord2f[0] = 0;
4287 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4288 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4289 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4290 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4291 r_bloomstate.bloomtexcoord2f[5] = 0;
4292 r_bloomstate.bloomtexcoord2f[6] = 0;
4293 r_bloomstate.bloomtexcoord2f[7] = 0;
4295 if (r_hdr.integer || r_bloom.integer)
4297 r_bloomstate.enabled = true;
4298 r_bloomstate.hdr = r_hdr.integer != 0;
4301 R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
4304 void R_Bloom_CopyBloomTexture(float colorscale)
4306 r_refdef.stats.bloom++;
4308 // scale down screen texture to the bloom texture size
4310 R_SetViewport(&r_bloomstate.viewport);
4311 GL_BlendFunc(GL_ONE, GL_ZERO);
4312 GL_Color(colorscale, colorscale, colorscale, 1);
4313 // TODO: optimize with multitexture or GLSL
4314 R_SetupGenericShader(true);
4315 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4316 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4317 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4318 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4320 // we now have a bloom image in the framebuffer
4321 // copy it into the bloom image texture for later processing
4322 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4323 GL_ActiveTexture(0);
4325 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4326 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4329 void R_Bloom_CopyHDRTexture(void)
4331 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4332 GL_ActiveTexture(0);
4334 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4335 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4338 void R_Bloom_MakeTexture(void)
4341 float xoffset, yoffset, r, brighten;
4343 r_refdef.stats.bloom++;
4345 R_ResetViewRendering2D();
4346 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4347 R_Mesh_ColorPointer(NULL, 0, 0);
4348 R_SetupGenericShader(true);
4350 // we have a bloom image in the framebuffer
4352 R_SetViewport(&r_bloomstate.viewport);
4354 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4357 r = bound(0, r_bloom_colorexponent.value / x, 1);
4358 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4359 GL_Color(r, r, r, 1);
4360 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4361 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4362 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4363 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4365 // copy the vertically blurred bloom view to a texture
4366 GL_ActiveTexture(0);
4368 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4369 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4372 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4373 brighten = r_bloom_brighten.value;
4375 brighten *= r_hdr_range.value;
4376 brighten = sqrt(brighten);
4378 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4379 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4380 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4382 for (dir = 0;dir < 2;dir++)
4384 // blend on at multiple vertical offsets to achieve a vertical blur
4385 // TODO: do offset blends using GLSL
4386 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4387 GL_BlendFunc(GL_ONE, GL_ZERO);
4388 for (x = -range;x <= range;x++)
4390 if (!dir){xoffset = 0;yoffset = x;}
4391 else {xoffset = x;yoffset = 0;}
4392 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4393 yoffset /= (float)r_bloomstate.bloomtextureheight;
4394 // compute a texcoord array with the specified x and y offset
4395 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4396 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4397 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4398 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4399 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4400 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4401 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4402 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4403 // this r value looks like a 'dot' particle, fading sharply to
4404 // black at the edges
4405 // (probably not realistic but looks good enough)
4406 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4407 //r = brighten/(range*2+1);
4408 r = brighten / (range * 2 + 1);
4410 r *= (1 - x*x/(float)(range*range));
4411 GL_Color(r, r, r, 1);
4412 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4413 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4414 GL_BlendFunc(GL_ONE, GL_ONE);
4417 // copy the vertically blurred bloom view to a texture
4418 GL_ActiveTexture(0);
4420 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4421 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4424 // apply subtract last
4425 // (just like it would be in a GLSL shader)
4426 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4428 GL_BlendFunc(GL_ONE, GL_ZERO);
4429 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4430 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4431 GL_Color(1, 1, 1, 1);
4432 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4433 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4435 GL_BlendFunc(GL_ONE, GL_ONE);
4436 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4437 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4438 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4439 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4440 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4441 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4442 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4444 // copy the darkened bloom view to a texture
4445 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4446 GL_ActiveTexture(0);
4448 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4449 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4453 void R_HDR_RenderBloomTexture(void)
4455 int oldwidth, oldheight;
4456 float oldcolorscale;
4458 oldcolorscale = r_refdef.view.colorscale;
4459 oldwidth = r_refdef.view.width;
4460 oldheight = r_refdef.view.height;
4461 r_refdef.view.width = r_bloomstate.bloomwidth;
4462 r_refdef.view.height = r_bloomstate.bloomheight;
4464 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4465 // TODO: add exposure compensation features
4466 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4468 r_refdef.view.showdebug = false;
4469 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4471 R_ResetViewRendering3D();
4473 R_ClearScreen(r_refdef.fogenabled);
4474 if (r_timereport_active)
4475 R_TimeReport("HDRclear");
4478 if (r_timereport_active)
4479 R_TimeReport("visibility");
4481 // only do secondary renders with HDR if r_hdr is 2 or higher
4482 r_waterstate.numwaterplanes = 0;
4483 if (r_waterstate.enabled && r_hdr.integer >= 2)
4484 R_RenderWaterPlanes();
4486 r_refdef.view.showdebug = true;
4488 r_waterstate.numwaterplanes = 0;
4490 R_ResetViewRendering2D();
4492 R_Bloom_CopyHDRTexture();
4493 R_Bloom_MakeTexture();
4495 // restore the view settings
4496 r_refdef.view.width = oldwidth;
4497 r_refdef.view.height = oldheight;
4498 r_refdef.view.colorscale = oldcolorscale;
4500 R_ResetViewRendering3D();
4502 R_ClearScreen(r_refdef.fogenabled);
4503 if (r_timereport_active)
4504 R_TimeReport("viewclear");
4507 static void R_BlendView(void)
4509 if (r_bloomstate.texture_screen)
4511 // make sure the buffer is available
4512 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4514 R_ResetViewRendering2D();
4515 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4516 R_Mesh_ColorPointer(NULL, 0, 0);
4517 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4518 GL_ActiveTexture(0);CHECKGLERROR
4520 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4522 // declare variables
4524 static float avgspeed;
4526 speed = VectorLength(cl.movement_velocity);
4528 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4529 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4531 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4532 speed = bound(0, speed, 1);
4533 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4535 // calculate values into a standard alpha
4536 cl.motionbluralpha = 1 - exp(-
4538 (r_motionblur.value * speed / 80)
4540 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4543 max(0.0001, cl.time - cl.oldtime) // fps independent
4546 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4547 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4549 if (cl.motionbluralpha > 0)
4551 R_SetupGenericShader(true);
4552 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4553 GL_Color(1, 1, 1, cl.motionbluralpha);
4554 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4555 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4556 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4557 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4561 // copy view into the screen texture
4562 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4563 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4566 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4568 unsigned int permutation =
4569 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4570 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4571 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4572 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4573 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4575 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4577 // render simple bloom effect
4578 // copy the screen and shrink it and darken it for the bloom process
4579 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4580 // make the bloom texture
4581 R_Bloom_MakeTexture();
4584 R_ResetViewRendering2D();
4585 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4586 R_Mesh_ColorPointer(NULL, 0, 0);
4587 GL_Color(1, 1, 1, 1);
4588 GL_BlendFunc(GL_ONE, GL_ZERO);
4589 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4590 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4591 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4592 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4593 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4594 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4595 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4596 if (r_glsl_permutation->loc_TintColor >= 0)
4597 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4598 if (r_glsl_permutation->loc_ClientTime >= 0)
4599 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4600 if (r_glsl_permutation->loc_PixelSize >= 0)
4601 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4602 if (r_glsl_permutation->loc_UserVec1 >= 0)
4604 float a=0, b=0, c=0, d=0;
4605 #if _MSC_VER >= 1400
4606 #define sscanf sscanf_s
4608 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4609 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4611 if (r_glsl_permutation->loc_UserVec2 >= 0)
4613 float a=0, b=0, c=0, d=0;
4614 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4615 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4617 if (r_glsl_permutation->loc_UserVec3 >= 0)
4619 float a=0, b=0, c=0, d=0;
4620 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4621 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4623 if (r_glsl_permutation->loc_UserVec4 >= 0)
4625 float a=0, b=0, c=0, d=0;
4626 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4627 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4629 if (r_glsl_permutation->loc_Saturation >= 0)
4630 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4631 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4632 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4638 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4640 // render high dynamic range bloom effect
4641 // the bloom texture was made earlier this render, so we just need to
4642 // blend it onto the screen...
4643 R_ResetViewRendering2D();
4644 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4645 R_Mesh_ColorPointer(NULL, 0, 0);
4646 R_SetupGenericShader(true);
4647 GL_Color(1, 1, 1, 1);
4648 GL_BlendFunc(GL_ONE, GL_ONE);
4649 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4650 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4651 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4652 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4654 else if (r_bloomstate.texture_bloom)
4656 // render simple bloom effect
4657 // copy the screen and shrink it and darken it for the bloom process
4658 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4659 // make the bloom texture
4660 R_Bloom_MakeTexture();
4661 // put the original screen image back in place and blend the bloom
4663 R_ResetViewRendering2D();
4664 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4665 R_Mesh_ColorPointer(NULL, 0, 0);
4666 GL_Color(1, 1, 1, 1);
4667 GL_BlendFunc(GL_ONE, GL_ZERO);
4668 // do both in one pass if possible
4669 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4670 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4671 if (r_textureunits.integer >= 2 && gl_combine.integer)
4673 R_SetupGenericTwoTextureShader(GL_ADD);
4674 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4675 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4679 R_SetupGenericShader(true);
4680 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4681 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4682 // now blend on the bloom texture
4683 GL_BlendFunc(GL_ONE, GL_ONE);
4684 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4685 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4687 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4688 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4690 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4692 // apply a color tint to the whole view
4693 R_ResetViewRendering2D();
4694 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4695 R_Mesh_ColorPointer(NULL, 0, 0);
4696 R_SetupGenericShader(false);
4697 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4698 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4699 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4703 matrix4x4_t r_waterscrollmatrix;
4705 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4707 if (r_refdef.fog_density)
4709 r_refdef.fogcolor[0] = r_refdef.fog_red;
4710 r_refdef.fogcolor[1] = r_refdef.fog_green;
4711 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4713 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4714 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4715 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4716 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4720 VectorCopy(r_refdef.fogcolor, fogvec);
4721 // color.rgb *= ContrastBoost * SceneBrightness;
4722 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4723 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4724 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4725 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4730 void R_UpdateVariables(void)
4734 r_refdef.scene.ambient = r_ambient.value;
4736 r_refdef.farclip = r_farclip_base.value;
4737 if (r_refdef.scene.worldmodel)
4738 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
4739 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4741 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4742 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4743 r_refdef.polygonfactor = 0;
4744 r_refdef.polygonoffset = 0;
4745 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4746 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4748 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4749 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4750 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4751 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4752 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4753 if (r_showsurfaces.integer)
4755 r_refdef.scene.rtworld = false;
4756 r_refdef.scene.rtworldshadows = false;
4757 r_refdef.scene.rtdlight = false;
4758 r_refdef.scene.rtdlightshadows = false;
4759 r_refdef.lightmapintensity = 0;
4762 if (gamemode == GAME_NEHAHRA)
4764 if (gl_fogenable.integer)
4766 r_refdef.oldgl_fogenable = true;
4767 r_refdef.fog_density = gl_fogdensity.value;
4768 r_refdef.fog_red = gl_fogred.value;
4769 r_refdef.fog_green = gl_foggreen.value;
4770 r_refdef.fog_blue = gl_fogblue.value;
4771 r_refdef.fog_alpha = 1;
4772 r_refdef.fog_start = 0;
4773 r_refdef.fog_end = gl_skyclip.value;
4774 r_refdef.fog_height = 1<<30;
4775 r_refdef.fog_fadedepth = 128;
4777 else if (r_refdef.oldgl_fogenable)
4779 r_refdef.oldgl_fogenable = false;
4780 r_refdef.fog_density = 0;
4781 r_refdef.fog_red = 0;
4782 r_refdef.fog_green = 0;
4783 r_refdef.fog_blue = 0;
4784 r_refdef.fog_alpha = 0;
4785 r_refdef.fog_start = 0;
4786 r_refdef.fog_end = 0;
4787 r_refdef.fog_height = 1<<30;
4788 r_refdef.fog_fadedepth = 128;
4792 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4793 r_refdef.fog_start = max(0, r_refdef.fog_start);
4794 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4796 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4798 if (r_refdef.fog_density && r_drawfog.integer)
4800 r_refdef.fogenabled = true;
4801 // this is the point where the fog reaches 0.9986 alpha, which we
4802 // consider a good enough cutoff point for the texture
4803 // (0.9986 * 256 == 255.6)
4804 if (r_fog_exp2.integer)
4805 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4807 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4808 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4809 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4810 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4811 // fog color was already set
4812 // update the fog texture
4813 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
4814 R_BuildFogTexture();
4817 r_refdef.fogenabled = false;
4819 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4821 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4823 // build GLSL gamma texture
4824 #define RAMPWIDTH 256
4825 unsigned short ramp[RAMPWIDTH * 3];
4826 unsigned char rampbgr[RAMPWIDTH][4];
4829 r_texture_gammaramps_serial = vid_gammatables_serial;
4831 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4832 for(i = 0; i < RAMPWIDTH; ++i)
4834 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4835 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4836 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4839 if (r_texture_gammaramps)
4841 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4845 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
4851 // remove GLSL gamma texture
4855 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4856 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4862 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4863 if( scenetype != r_currentscenetype ) {
4864 // store the old scenetype
4865 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4866 r_currentscenetype = scenetype;
4867 // move in the new scene
4868 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4877 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4879 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4880 if( scenetype == r_currentscenetype ) {
4881 return &r_refdef.scene;
4883 return &r_scenes_store[ scenetype ];
4892 void R_RenderView(void)
4894 if (r_timereport_active)
4895 R_TimeReport("start");
4896 r_frame++; // used only by R_GetCurrentTexture
4897 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4899 R_AnimCache_NewFrame();
4901 if (r_refdef.view.isoverlay)
4903 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4904 GL_Clear( GL_DEPTH_BUFFER_BIT );
4905 R_TimeReport("depthclear");
4907 r_refdef.view.showdebug = false;
4909 r_waterstate.enabled = false;
4910 r_waterstate.numwaterplanes = 0;
4918 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4919 return; //Host_Error ("R_RenderView: NULL worldmodel");
4921 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4923 // break apart the view matrix into vectors for various purposes
4924 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4925 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4926 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4927 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4928 // make an inverted copy of the view matrix for tracking sprites
4929 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4931 R_Shadow_UpdateWorldLightSelection();
4933 R_Bloom_StartFrame();
4934 R_Water_StartFrame();
4937 if (r_timereport_active)
4938 R_TimeReport("viewsetup");
4940 R_ResetViewRendering3D();
4942 if (r_refdef.view.clear || r_refdef.fogenabled)
4944 R_ClearScreen(r_refdef.fogenabled);
4945 if (r_timereport_active)
4946 R_TimeReport("viewclear");
4948 r_refdef.view.clear = true;
4950 // this produces a bloom texture to be used in R_BlendView() later
4952 R_HDR_RenderBloomTexture();
4954 r_refdef.view.showdebug = true;
4957 if (r_timereport_active)
4958 R_TimeReport("visibility");
4960 r_waterstate.numwaterplanes = 0;
4961 if (r_waterstate.enabled)
4962 R_RenderWaterPlanes();
4965 r_waterstate.numwaterplanes = 0;
4968 if (r_timereport_active)
4969 R_TimeReport("blendview");
4971 GL_Scissor(0, 0, vid.width, vid.height);
4972 GL_ScissorTest(false);
4976 void R_RenderWaterPlanes(void)
4978 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4980 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4981 if (r_timereport_active)
4982 R_TimeReport("waterworld");
4985 // don't let sound skip if going slow
4986 if (r_refdef.scene.extraupdate)
4989 R_DrawModelsAddWaterPlanes();
4990 if (r_timereport_active)
4991 R_TimeReport("watermodels");
4993 if (r_waterstate.numwaterplanes)
4995 R_Water_ProcessPlanes();
4996 if (r_timereport_active)
4997 R_TimeReport("waterscenes");
5001 extern void R_DrawLightningBeams (void);
5002 extern void VM_CL_AddPolygonsToMeshQueue (void);
5003 extern void R_DrawPortals (void);
5004 extern cvar_t cl_locs_show;
5005 static void R_DrawLocs(void);
5006 static void R_DrawEntityBBoxes(void);
5007 extern cvar_t cl_decals_newsystem;
5008 void R_RenderScene(void)
5010 r_refdef.stats.renders++;
5014 // don't let sound skip if going slow
5015 if (r_refdef.scene.extraupdate)
5018 R_MeshQueue_BeginScene();
5022 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);
5024 if (cl.csqc_vidvars.drawworld)
5026 // don't let sound skip if going slow
5027 if (r_refdef.scene.extraupdate)
5030 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5032 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5033 if (r_timereport_active)
5034 R_TimeReport("worldsky");
5037 if (R_DrawBrushModelsSky() && r_timereport_active)
5038 R_TimeReport("bmodelsky");
5040 if (skyrendermasked && skyrenderlater)
5042 // we have to force off the water clipping plane while rendering sky
5049 R_AnimCache_CacheVisibleEntities();
5051 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5053 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5054 if (r_timereport_active)
5055 R_TimeReport("worlddepth");
5057 if (r_depthfirst.integer >= 2)
5059 R_DrawModelsDepth();
5060 if (r_timereport_active)
5061 R_TimeReport("modeldepth");
5064 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5066 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5067 if (r_timereport_active)
5068 R_TimeReport("world");
5071 // don't let sound skip if going slow
5072 if (r_refdef.scene.extraupdate)
5076 if (r_timereport_active)
5077 R_TimeReport("models");
5079 // don't let sound skip if going slow
5080 if (r_refdef.scene.extraupdate)
5083 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5085 R_DrawModelShadows();
5086 R_ResetViewRendering3D();
5087 // don't let sound skip if going slow
5088 if (r_refdef.scene.extraupdate)
5092 R_ShadowVolumeLighting(false);
5093 if (r_timereport_active)
5094 R_TimeReport("rtlights");
5096 // don't let sound skip if going slow
5097 if (r_refdef.scene.extraupdate)
5100 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5102 R_DrawModelShadows();
5103 R_ResetViewRendering3D();
5104 // don't let sound skip if going slow
5105 if (r_refdef.scene.extraupdate)
5109 if (cl.csqc_vidvars.drawworld)
5111 if (cl_decals_newsystem.integer)
5113 R_DrawModelDecals();
5114 if (r_timereport_active)
5115 R_TimeReport("modeldecals");
5120 if (r_timereport_active)
5121 R_TimeReport("decals");
5125 if (r_timereport_active)
5126 R_TimeReport("particles");
5129 if (r_timereport_active)
5130 R_TimeReport("explosions");
5132 R_DrawLightningBeams();
5133 if (r_timereport_active)
5134 R_TimeReport("lightning");
5137 R_SetupGenericShader(true);
5138 VM_CL_AddPolygonsToMeshQueue();
5140 if (r_refdef.view.showdebug)
5142 if (cl_locs_show.integer)
5145 if (r_timereport_active)
5146 R_TimeReport("showlocs");
5149 if (r_drawportals.integer)
5152 if (r_timereport_active)
5153 R_TimeReport("portals");
5156 if (r_showbboxes.value > 0)
5158 R_DrawEntityBBoxes();
5159 if (r_timereport_active)
5160 R_TimeReport("bboxes");
5164 R_SetupGenericShader(true);
5165 R_MeshQueue_RenderTransparent();
5166 if (r_timereport_active)
5167 R_TimeReport("drawtrans");
5169 R_SetupGenericShader(true);
5171 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))
5173 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5174 if (r_timereport_active)
5175 R_TimeReport("worlddebug");
5176 R_DrawModelsDebug();
5177 if (r_timereport_active)
5178 R_TimeReport("modeldebug");
5181 R_SetupGenericShader(true);
5183 if (cl.csqc_vidvars.drawworld)
5186 if (r_timereport_active)
5187 R_TimeReport("coronas");
5190 // don't let sound skip if going slow
5191 if (r_refdef.scene.extraupdate)
5194 R_ResetViewRendering2D();
5197 static const unsigned short bboxelements[36] =
5207 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5210 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5212 RSurf_ActiveWorldEntity();
5214 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5215 GL_DepthMask(false);
5216 GL_DepthRange(0, 1);
5217 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5218 R_Mesh_ResetTextureState();
5220 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5221 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5222 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5223 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5224 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5225 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5226 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5227 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5228 R_FillColors(color4f, 8, cr, cg, cb, ca);
5229 if (r_refdef.fogenabled)
5231 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5233 f1 = RSurf_FogVertex(v);
5235 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5236 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5237 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5240 R_Mesh_VertexPointer(vertex3f, 0, 0);
5241 R_Mesh_ColorPointer(color4f, 0, 0);
5242 R_Mesh_ResetTextureState();
5243 R_SetupGenericShader(false);
5244 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5247 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5251 prvm_edict_t *edict;
5252 prvm_prog_t *prog_save = prog;
5254 // this function draws bounding boxes of server entities
5258 GL_CullFace(GL_NONE);
5259 R_SetupGenericShader(false);
5263 for (i = 0;i < numsurfaces;i++)
5265 edict = PRVM_EDICT_NUM(surfacelist[i]);
5266 switch ((int)edict->fields.server->solid)
5268 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5269 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5270 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5271 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5272 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5273 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5275 color[3] *= r_showbboxes.value;
5276 color[3] = bound(0, color[3], 1);
5277 GL_DepthTest(!r_showdisabledepthtest.integer);
5278 GL_CullFace(r_refdef.view.cullface_front);
5279 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5285 static void R_DrawEntityBBoxes(void)
5288 prvm_edict_t *edict;
5290 prvm_prog_t *prog_save = prog;
5292 // this function draws bounding boxes of server entities
5298 for (i = 0;i < prog->num_edicts;i++)
5300 edict = PRVM_EDICT_NUM(i);
5301 if (edict->priv.server->free)
5303 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5304 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5306 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5308 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5309 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5315 static const int nomodelelement3i[24] =
5327 static const unsigned short nomodelelement3s[24] =
5339 static const float nomodelvertex3f[6*3] =
5349 static const float nomodelcolor4f[6*4] =
5351 0.0f, 0.0f, 0.5f, 1.0f,
5352 0.0f, 0.0f, 0.5f, 1.0f,
5353 0.0f, 0.5f, 0.0f, 1.0f,
5354 0.0f, 0.5f, 0.0f, 1.0f,
5355 0.5f, 0.0f, 0.0f, 1.0f,
5356 0.5f, 0.0f, 0.0f, 1.0f
5359 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5365 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);
5367 // this is only called once per entity so numsurfaces is always 1, and
5368 // surfacelist is always {0}, so this code does not handle batches
5370 if (rsurface.ent_flags & RENDER_ADDITIVE)
5372 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5373 GL_DepthMask(false);
5375 else if (rsurface.ent_color[3] < 1)
5377 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5378 GL_DepthMask(false);
5382 GL_BlendFunc(GL_ONE, GL_ZERO);
5385 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5386 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5387 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5388 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5389 R_SetupGenericShader(false);
5390 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5391 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5392 R_Mesh_ColorPointer(color4f, 0, 0);
5393 for (i = 0, c = color4f;i < 6;i++, c += 4)
5395 c[0] *= rsurface.ent_color[0];
5396 c[1] *= rsurface.ent_color[1];
5397 c[2] *= rsurface.ent_color[2];
5398 c[3] *= rsurface.ent_color[3];
5400 if (r_refdef.fogenabled)
5402 for (i = 0, c = color4f;i < 6;i++, c += 4)
5404 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5406 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5407 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5408 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5411 R_Mesh_ResetTextureState();
5412 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5415 void R_DrawNoModel(entity_render_t *ent)
5418 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5419 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5420 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5422 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5425 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5427 vec3_t right1, right2, diff, normal;
5429 VectorSubtract (org2, org1, normal);
5431 // calculate 'right' vector for start
5432 VectorSubtract (r_refdef.view.origin, org1, diff);
5433 CrossProduct (normal, diff, right1);
5434 VectorNormalize (right1);
5436 // calculate 'right' vector for end
5437 VectorSubtract (r_refdef.view.origin, org2, diff);
5438 CrossProduct (normal, diff, right2);
5439 VectorNormalize (right2);
5441 vert[ 0] = org1[0] + width * right1[0];
5442 vert[ 1] = org1[1] + width * right1[1];
5443 vert[ 2] = org1[2] + width * right1[2];
5444 vert[ 3] = org1[0] - width * right1[0];
5445 vert[ 4] = org1[1] - width * right1[1];
5446 vert[ 5] = org1[2] - width * right1[2];
5447 vert[ 6] = org2[0] - width * right2[0];
5448 vert[ 7] = org2[1] - width * right2[1];
5449 vert[ 8] = org2[2] - width * right2[2];
5450 vert[ 9] = org2[0] + width * right2[0];
5451 vert[10] = org2[1] + width * right2[1];
5452 vert[11] = org2[2] + width * right2[2];
5455 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)
5457 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5458 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5459 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5460 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5461 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5462 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5463 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5464 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5465 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5466 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5467 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5468 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5471 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5476 VectorSet(v, x, y, z);
5477 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5478 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5480 if (i == mesh->numvertices)
5482 if (mesh->numvertices < mesh->maxvertices)
5484 VectorCopy(v, vertex3f);
5485 mesh->numvertices++;
5487 return mesh->numvertices;
5493 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5497 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5498 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5499 e = mesh->element3i + mesh->numtriangles * 3;
5500 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5502 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5503 if (mesh->numtriangles < mesh->maxtriangles)
5508 mesh->numtriangles++;
5510 element[1] = element[2];
5514 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5518 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5519 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5520 e = mesh->element3i + mesh->numtriangles * 3;
5521 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5523 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5524 if (mesh->numtriangles < mesh->maxtriangles)
5529 mesh->numtriangles++;
5531 element[1] = element[2];
5535 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5536 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5538 int planenum, planenum2;
5541 mplane_t *plane, *plane2;
5543 double temppoints[2][256*3];
5544 // figure out how large a bounding box we need to properly compute this brush
5546 for (w = 0;w < numplanes;w++)
5547 maxdist = max(maxdist, fabs(planes[w].dist));
5548 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5549 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5550 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5554 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5555 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5557 if (planenum2 == planenum)
5559 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);
5562 if (tempnumpoints < 3)
5564 // generate elements forming a triangle fan for this polygon
5565 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5569 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)
5571 texturelayer_t *layer;
5572 layer = t->currentlayers + t->currentnumlayers++;
5574 layer->depthmask = depthmask;
5575 layer->blendfunc1 = blendfunc1;
5576 layer->blendfunc2 = blendfunc2;
5577 layer->texture = texture;
5578 layer->texmatrix = *matrix;
5579 layer->color[0] = r * r_refdef.view.colorscale;
5580 layer->color[1] = g * r_refdef.view.colorscale;
5581 layer->color[2] = b * r_refdef.view.colorscale;
5582 layer->color[3] = a;
5585 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5588 index = parms[2] + r_refdef.scene.time * parms[3];
5589 index -= floor(index);
5593 case Q3WAVEFUNC_NONE:
5594 case Q3WAVEFUNC_NOISE:
5595 case Q3WAVEFUNC_COUNT:
5598 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5599 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5600 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5601 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5602 case Q3WAVEFUNC_TRIANGLE:
5604 f = index - floor(index);
5615 return (float)(parms[0] + parms[1] * f);
5618 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5623 matrix4x4_t matrix, temp;
5624 switch(tcmod->tcmod)
5628 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5629 matrix = r_waterscrollmatrix;
5631 matrix = identitymatrix;
5633 case Q3TCMOD_ENTITYTRANSLATE:
5634 // this is used in Q3 to allow the gamecode to control texcoord
5635 // scrolling on the entity, which is not supported in darkplaces yet.
5636 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5638 case Q3TCMOD_ROTATE:
5639 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5640 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5641 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5644 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5646 case Q3TCMOD_SCROLL:
5647 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5649 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5650 w = (int) tcmod->parms[0];
5651 h = (int) tcmod->parms[1];
5652 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5654 idx = (int) floor(f * w * h);
5655 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5657 case Q3TCMOD_STRETCH:
5658 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5659 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5661 case Q3TCMOD_TRANSFORM:
5662 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5663 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5664 VectorSet(tcmat + 6, 0 , 0 , 1);
5665 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5666 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5668 case Q3TCMOD_TURBULENT:
5669 // this is handled in the RSurf_PrepareVertices function
5670 matrix = identitymatrix;
5674 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5677 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5679 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5680 char name[MAX_QPATH];
5681 skinframe_t *skinframe;
5682 unsigned char pixels[296*194];
5683 strlcpy(cache->name, skinname, sizeof(cache->name));
5684 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5685 if (developer_loading.integer)
5686 Con_Printf("loading %s\n", name);
5687 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5688 if (!skinframe || !skinframe->base)
5691 fs_offset_t filesize;
5693 f = FS_LoadFile(name, tempmempool, true, &filesize);
5696 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5697 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5701 cache->skinframe = skinframe;
5704 texture_t *R_GetCurrentTexture(texture_t *t)
5707 const entity_render_t *ent = rsurface.entity;
5708 dp_model_t *model = ent->model;
5709 q3shaderinfo_layer_tcmod_t *tcmod;
5711 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5712 return t->currentframe;
5713 t->update_lastrenderframe = r_frame;
5714 t->update_lastrenderentity = (void *)ent;
5716 // switch to an alternate material if this is a q1bsp animated material
5718 texture_t *texture = t;
5719 int s = rsurface.ent_skinnum;
5720 if ((unsigned int)s >= (unsigned int)model->numskins)
5722 if (model->skinscenes)
5724 if (model->skinscenes[s].framecount > 1)
5725 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5727 s = model->skinscenes[s].firstframe;
5730 t = t + s * model->num_surfaces;
5733 // use an alternate animation if the entity's frame is not 0,
5734 // and only if the texture has an alternate animation
5735 if (rsurface.ent_alttextures && t->anim_total[1])
5736 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5738 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5740 texture->currentframe = t;
5743 // update currentskinframe to be a qw skin or animation frame
5744 if (rsurface.ent_qwskin >= 0)
5746 i = rsurface.ent_qwskin;
5747 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5749 r_qwskincache_size = cl.maxclients;
5751 Mem_Free(r_qwskincache);
5752 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5754 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5755 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5756 t->currentskinframe = r_qwskincache[i].skinframe;
5757 if (t->currentskinframe == NULL)
5758 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5760 else if (t->numskinframes >= 2)
5761 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5762 if (t->backgroundnumskinframes >= 2)
5763 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5765 t->currentmaterialflags = t->basematerialflags;
5766 t->currentalpha = rsurface.ent_color[3];
5767 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5768 t->currentalpha *= r_wateralpha.value;
5769 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5770 t->currentalpha *= t->r_water_wateralpha;
5771 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5772 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5773 if (!(rsurface.ent_flags & RENDER_LIGHT))
5774 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5775 else if (rsurface.modeltexcoordlightmap2f == NULL)
5777 // pick a model lighting mode
5778 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5779 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5781 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5783 if (rsurface.ent_flags & RENDER_ADDITIVE)
5784 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5785 else if (t->currentalpha < 1)
5786 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5787 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5788 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5789 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5790 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5791 if (t->backgroundnumskinframes)
5792 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5793 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5795 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5796 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5799 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5801 // there is no tcmod
5802 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5804 t->currenttexmatrix = r_waterscrollmatrix;
5805 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5807 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
5809 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5810 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5813 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5814 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5815 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5816 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5818 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5819 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5820 t->glosstexture = r_texture_black;
5821 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5822 t->backgroundglosstexture = r_texture_black;
5823 t->specularpower = r_shadow_glossexponent.value;
5824 // TODO: store reference values for these in the texture?
5825 t->specularscale = 0;
5826 if (r_shadow_gloss.integer > 0)
5828 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5830 if (r_shadow_glossintensity.value > 0)
5832 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5833 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5834 t->specularscale = r_shadow_glossintensity.value;
5837 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5839 t->glosstexture = r_texture_white;
5840 t->backgroundglosstexture = r_texture_white;
5841 t->specularscale = r_shadow_gloss2intensity.value;
5842 t->specularpower = r_shadow_gloss2exponent.value;
5845 t->specularscale *= t->specularscalemod;
5846 t->specularpower *= t->specularpowermod;
5848 // lightmaps mode looks bad with dlights using actual texturing, so turn
5849 // off the colormap and glossmap, but leave the normalmap on as it still
5850 // accurately represents the shading involved
5851 if (gl_lightmaps.integer)
5853 t->basetexture = r_texture_grey128;
5854 t->backgroundbasetexture = NULL;
5855 t->specularscale = 0;
5856 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5859 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5860 VectorClear(t->dlightcolor);
5861 t->currentnumlayers = 0;
5862 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5865 int blendfunc1, blendfunc2;
5867 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5869 blendfunc1 = GL_SRC_ALPHA;
5870 blendfunc2 = GL_ONE;
5872 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5874 blendfunc1 = GL_SRC_ALPHA;
5875 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5877 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5879 blendfunc1 = t->customblendfunc[0];
5880 blendfunc2 = t->customblendfunc[1];
5884 blendfunc1 = GL_ONE;
5885 blendfunc2 = GL_ZERO;
5887 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5888 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5889 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5890 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5892 // fullbright is not affected by r_refdef.lightmapintensity
5893 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]);
5894 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5895 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]);
5896 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5897 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]);
5901 vec3_t ambientcolor;
5903 // set the color tint used for lights affecting this surface
5904 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5906 // q3bsp has no lightmap updates, so the lightstylevalue that
5907 // would normally be baked into the lightmap must be
5908 // applied to the color
5909 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5910 if (model->type == mod_brushq3)
5911 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5912 colorscale *= r_refdef.lightmapintensity;
5913 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5914 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5915 // basic lit geometry
5916 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]);
5917 // add pants/shirt if needed
5918 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5919 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]);
5920 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5921 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]);
5922 // now add ambient passes if needed
5923 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5925 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]);
5926 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5927 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]);
5928 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5929 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]);
5932 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5933 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]);
5934 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5936 // if this is opaque use alpha blend which will darken the earlier
5939 // if this is an alpha blended material, all the earlier passes
5940 // were darkened by fog already, so we only need to add the fog
5941 // color ontop through the fog mask texture
5943 // if this is an additive blended material, all the earlier passes
5944 // were darkened by fog already, and we should not add fog color
5945 // (because the background was not darkened, there is no fog color
5946 // that was lost behind it).
5947 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]);
5951 return t->currentframe;
5954 rsurfacestate_t rsurface;
5956 void R_Mesh_ResizeArrays(int newvertices)
5959 if (rsurface.array_size >= newvertices)
5961 if (rsurface.array_modelvertex3f)
5962 Mem_Free(rsurface.array_modelvertex3f);
5963 rsurface.array_size = (newvertices + 1023) & ~1023;
5964 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5965 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5966 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5967 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5968 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5969 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5970 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5971 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5972 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5973 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5974 rsurface.array_color4f = base + rsurface.array_size * 27;
5975 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5978 void RSurf_ActiveWorldEntity(void)
5980 dp_model_t *model = r_refdef.scene.worldmodel;
5981 //if (rsurface.entity == r_refdef.scene.worldentity)
5983 rsurface.entity = r_refdef.scene.worldentity;
5984 rsurface.ent_skinnum = 0;
5985 rsurface.ent_qwskin = -1;
5986 rsurface.ent_shadertime = 0;
5987 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
5988 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
5989 if (rsurface.array_size < model->surfmesh.num_vertices)
5990 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5991 rsurface.matrix = identitymatrix;
5992 rsurface.inversematrix = identitymatrix;
5993 rsurface.matrixscale = 1;
5994 rsurface.inversematrixscale = 1;
5995 R_Mesh_Matrix(&identitymatrix);
5996 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5997 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
5998 rsurface.fograngerecip = r_refdef.fograngerecip;
5999 rsurface.fogheightfade = r_refdef.fogheightfade;
6000 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6001 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6002 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6003 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6004 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6005 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6006 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6007 VectorSet(rsurface.glowmod, 1, 1, 1);
6008 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6009 rsurface.frameblend[0].lerp = 1;
6010 rsurface.ent_alttextures = false;
6011 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6012 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6013 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6014 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6015 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6016 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6017 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6018 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6019 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6020 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6021 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6022 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6023 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6024 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6025 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6026 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6027 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6028 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6029 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6030 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6031 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6032 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6033 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6034 rsurface.modelelement3i = model->surfmesh.data_element3i;
6035 rsurface.modelelement3s = model->surfmesh.data_element3s;
6036 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6037 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6038 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6039 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6040 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6041 rsurface.modelsurfaces = model->data_surfaces;
6042 rsurface.generatedvertex = false;
6043 rsurface.vertex3f = rsurface.modelvertex3f;
6044 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6045 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6046 rsurface.svector3f = rsurface.modelsvector3f;
6047 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6048 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6049 rsurface.tvector3f = rsurface.modeltvector3f;
6050 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6051 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6052 rsurface.normal3f = rsurface.modelnormal3f;
6053 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6054 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6055 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6058 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6060 dp_model_t *model = ent->model;
6061 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6063 rsurface.entity = (entity_render_t *)ent;
6064 rsurface.ent_skinnum = ent->skinnum;
6065 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;
6066 rsurface.ent_shadertime = ent->shadertime;
6067 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6068 rsurface.ent_flags = ent->flags;
6069 if (rsurface.array_size < model->surfmesh.num_vertices)
6070 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6071 rsurface.matrix = ent->matrix;
6072 rsurface.inversematrix = ent->inversematrix;
6073 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6074 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6075 R_Mesh_Matrix(&rsurface.matrix);
6076 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6077 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6078 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6079 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6080 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6081 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6082 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6083 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6084 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6085 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6086 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6087 VectorCopy(ent->glowmod, rsurface.glowmod);
6088 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6089 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6090 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6091 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6092 if (ent->model->brush.submodel)
6094 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6095 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6097 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6099 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6101 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6102 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6103 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6104 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6106 else if (wanttangents)
6108 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6109 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6110 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6111 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6112 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6114 else if (wantnormals)
6116 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6117 rsurface.modelsvector3f = NULL;
6118 rsurface.modeltvector3f = NULL;
6119 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6120 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6124 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6125 rsurface.modelsvector3f = NULL;
6126 rsurface.modeltvector3f = NULL;
6127 rsurface.modelnormal3f = NULL;
6128 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6130 rsurface.modelvertex3f_bufferobject = 0;
6131 rsurface.modelvertex3f_bufferoffset = 0;
6132 rsurface.modelsvector3f_bufferobject = 0;
6133 rsurface.modelsvector3f_bufferoffset = 0;
6134 rsurface.modeltvector3f_bufferobject = 0;
6135 rsurface.modeltvector3f_bufferoffset = 0;
6136 rsurface.modelnormal3f_bufferobject = 0;
6137 rsurface.modelnormal3f_bufferoffset = 0;
6138 rsurface.generatedvertex = true;
6142 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6143 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6144 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6145 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6146 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6147 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6148 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6149 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6150 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6151 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6152 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6153 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6154 rsurface.generatedvertex = false;
6156 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6157 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6158 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6159 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6160 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6161 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6162 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6163 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6164 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6165 rsurface.modelelement3i = model->surfmesh.data_element3i;
6166 rsurface.modelelement3s = model->surfmesh.data_element3s;
6167 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6168 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6169 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6170 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6171 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6172 rsurface.modelsurfaces = model->data_surfaces;
6173 rsurface.vertex3f = rsurface.modelvertex3f;
6174 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6175 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6176 rsurface.svector3f = rsurface.modelsvector3f;
6177 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6178 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6179 rsurface.tvector3f = rsurface.modeltvector3f;
6180 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6181 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6182 rsurface.normal3f = rsurface.modelnormal3f;
6183 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6184 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6185 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6188 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)
6190 rsurface.entity = r_refdef.scene.worldentity;
6191 rsurface.ent_skinnum = 0;
6192 rsurface.ent_qwskin = -1;
6193 rsurface.ent_shadertime = shadertime;
6194 Vector4Set(rsurface.ent_color, r, g, b, a);
6195 rsurface.ent_flags = entflags;
6196 rsurface.modelnum_vertices = numvertices;
6197 rsurface.modelnum_triangles = numtriangles;
6198 if (rsurface.array_size < rsurface.modelnum_vertices)
6199 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6200 rsurface.matrix = *matrix;
6201 rsurface.inversematrix = *inversematrix;
6202 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6203 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6204 R_Mesh_Matrix(&rsurface.matrix);
6205 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6206 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6207 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6208 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6209 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6210 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6211 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6212 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6213 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6214 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6215 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6216 VectorSet(rsurface.glowmod, 1, 1, 1);
6217 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6218 rsurface.frameblend[0].lerp = 1;
6219 rsurface.ent_alttextures = false;
6220 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6221 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6224 rsurface.modelvertex3f = vertex3f;
6225 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6226 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6227 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6229 else if (wantnormals)
6231 rsurface.modelvertex3f = vertex3f;
6232 rsurface.modelsvector3f = NULL;
6233 rsurface.modeltvector3f = NULL;
6234 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6238 rsurface.modelvertex3f = vertex3f;
6239 rsurface.modelsvector3f = NULL;
6240 rsurface.modeltvector3f = NULL;
6241 rsurface.modelnormal3f = NULL;
6243 rsurface.modelvertex3f_bufferobject = 0;
6244 rsurface.modelvertex3f_bufferoffset = 0;
6245 rsurface.modelsvector3f_bufferobject = 0;
6246 rsurface.modelsvector3f_bufferoffset = 0;
6247 rsurface.modeltvector3f_bufferobject = 0;
6248 rsurface.modeltvector3f_bufferoffset = 0;
6249 rsurface.modelnormal3f_bufferobject = 0;
6250 rsurface.modelnormal3f_bufferoffset = 0;
6251 rsurface.generatedvertex = true;
6252 rsurface.modellightmapcolor4f = color4f;
6253 rsurface.modellightmapcolor4f_bufferobject = 0;
6254 rsurface.modellightmapcolor4f_bufferoffset = 0;
6255 rsurface.modeltexcoordtexture2f = texcoord2f;
6256 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6257 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6258 rsurface.modeltexcoordlightmap2f = NULL;
6259 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6260 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6261 rsurface.modelelement3i = element3i;
6262 rsurface.modelelement3s = element3s;
6263 rsurface.modelelement3i_bufferobject = 0;
6264 rsurface.modelelement3s_bufferobject = 0;
6265 rsurface.modellightmapoffsets = NULL;
6266 rsurface.modelsurfaces = NULL;
6267 rsurface.vertex3f = rsurface.modelvertex3f;
6268 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6269 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6270 rsurface.svector3f = rsurface.modelsvector3f;
6271 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6272 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6273 rsurface.tvector3f = rsurface.modeltvector3f;
6274 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6275 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6276 rsurface.normal3f = rsurface.modelnormal3f;
6277 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6278 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6279 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6281 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6283 if ((wantnormals || wanttangents) && !normal3f)
6284 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6285 if (wanttangents && !svector3f)
6286 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);
6290 float RSurf_FogPoint(const float *v)
6292 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6293 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6294 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6295 float FogHeightFade = r_refdef.fogheightfade;
6297 unsigned int fogmasktableindex;
6298 if (r_refdef.fogplaneviewabove)
6299 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6301 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6302 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6303 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6306 float RSurf_FogVertex(const float *v)
6308 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6309 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6310 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6311 float FogHeightFade = rsurface.fogheightfade;
6313 unsigned int fogmasktableindex;
6314 if (r_refdef.fogplaneviewabove)
6315 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6317 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6318 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6319 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6322 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6323 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6326 int texturesurfaceindex;
6331 const float *v1, *in_tc;
6333 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6335 q3shaderinfo_deform_t *deform;
6336 // 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
6337 if (rsurface.generatedvertex)
6339 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6340 generatenormals = true;
6341 for (i = 0;i < Q3MAXDEFORMS;i++)
6343 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6345 generatetangents = true;
6346 generatenormals = true;
6348 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6349 generatenormals = true;
6351 if (generatenormals && !rsurface.modelnormal3f)
6353 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6354 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6355 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6356 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6358 if (generatetangents && !rsurface.modelsvector3f)
6360 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6361 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6362 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6363 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6364 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6365 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6366 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);
6369 rsurface.vertex3f = rsurface.modelvertex3f;
6370 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6371 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6372 rsurface.svector3f = rsurface.modelsvector3f;
6373 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6374 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6375 rsurface.tvector3f = rsurface.modeltvector3f;
6376 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6377 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6378 rsurface.normal3f = rsurface.modelnormal3f;
6379 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6380 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6381 // if vertices are deformed (sprite flares and things in maps, possibly
6382 // water waves, bulges and other deformations), generate them into
6383 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6384 // (may be static model data or generated data for an animated model, or
6385 // the previous deform pass)
6386 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6388 switch (deform->deform)
6391 case Q3DEFORM_PROJECTIONSHADOW:
6392 case Q3DEFORM_TEXT0:
6393 case Q3DEFORM_TEXT1:
6394 case Q3DEFORM_TEXT2:
6395 case Q3DEFORM_TEXT3:
6396 case Q3DEFORM_TEXT4:
6397 case Q3DEFORM_TEXT5:
6398 case Q3DEFORM_TEXT6:
6399 case Q3DEFORM_TEXT7:
6402 case Q3DEFORM_AUTOSPRITE:
6403 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6404 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6405 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6406 VectorNormalize(newforward);
6407 VectorNormalize(newright);
6408 VectorNormalize(newup);
6409 // make deformed versions of only the model vertices used by the specified surfaces
6410 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6412 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6413 // a single autosprite surface can contain multiple sprites...
6414 for (j = 0;j < surface->num_vertices - 3;j += 4)
6416 VectorClear(center);
6417 for (i = 0;i < 4;i++)
6418 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6419 VectorScale(center, 0.25f, center);
6420 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6421 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6422 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6423 for (i = 0;i < 4;i++)
6425 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6426 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6429 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);
6430 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);
6432 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6433 rsurface.vertex3f_bufferobject = 0;
6434 rsurface.vertex3f_bufferoffset = 0;
6435 rsurface.svector3f = rsurface.array_deformedsvector3f;
6436 rsurface.svector3f_bufferobject = 0;
6437 rsurface.svector3f_bufferoffset = 0;
6438 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6439 rsurface.tvector3f_bufferobject = 0;
6440 rsurface.tvector3f_bufferoffset = 0;
6441 rsurface.normal3f = rsurface.array_deformednormal3f;
6442 rsurface.normal3f_bufferobject = 0;
6443 rsurface.normal3f_bufferoffset = 0;
6445 case Q3DEFORM_AUTOSPRITE2:
6446 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6447 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6448 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6449 VectorNormalize(newforward);
6450 VectorNormalize(newright);
6451 VectorNormalize(newup);
6452 // make deformed versions of only the model vertices used by the specified surfaces
6453 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6455 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6456 const float *v1, *v2;
6466 memset(shortest, 0, sizeof(shortest));
6467 // a single autosprite surface can contain multiple sprites...
6468 for (j = 0;j < surface->num_vertices - 3;j += 4)
6470 VectorClear(center);
6471 for (i = 0;i < 4;i++)
6472 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6473 VectorScale(center, 0.25f, center);
6474 // find the two shortest edges, then use them to define the
6475 // axis vectors for rotating around the central axis
6476 for (i = 0;i < 6;i++)
6478 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6479 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6481 Debug_PolygonBegin(NULL, 0);
6482 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6483 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);
6484 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6487 l = VectorDistance2(v1, v2);
6488 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6490 l += (1.0f / 1024.0f);
6491 if (shortest[0].length2 > l || i == 0)
6493 shortest[1] = shortest[0];
6494 shortest[0].length2 = l;
6495 shortest[0].v1 = v1;
6496 shortest[0].v2 = v2;
6498 else if (shortest[1].length2 > l || i == 1)
6500 shortest[1].length2 = l;
6501 shortest[1].v1 = v1;
6502 shortest[1].v2 = v2;
6505 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6506 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6508 Debug_PolygonBegin(NULL, 0);
6509 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6510 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);
6511 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6514 // this calculates the right vector from the shortest edge
6515 // and the up vector from the edge midpoints
6516 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6517 VectorNormalize(right);
6518 VectorSubtract(end, start, up);
6519 VectorNormalize(up);
6520 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6521 VectorSubtract(rsurface.localvieworigin, center, forward);
6522 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6523 VectorNegate(forward, forward);
6524 VectorReflect(forward, 0, up, forward);
6525 VectorNormalize(forward);
6526 CrossProduct(up, forward, newright);
6527 VectorNormalize(newright);
6529 Debug_PolygonBegin(NULL, 0);
6530 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);
6531 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6532 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6536 Debug_PolygonBegin(NULL, 0);
6537 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6538 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6539 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6542 // rotate the quad around the up axis vector, this is made
6543 // especially easy by the fact we know the quad is flat,
6544 // so we only have to subtract the center position and
6545 // measure distance along the right vector, and then
6546 // multiply that by the newright vector and add back the
6548 // we also need to subtract the old position to undo the
6549 // displacement from the center, which we do with a
6550 // DotProduct, the subtraction/addition of center is also
6551 // optimized into DotProducts here
6552 l = DotProduct(right, center);
6553 for (i = 0;i < 4;i++)
6555 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6556 f = DotProduct(right, v1) - l;
6557 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6560 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);
6561 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);
6563 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6564 rsurface.vertex3f_bufferobject = 0;
6565 rsurface.vertex3f_bufferoffset = 0;
6566 rsurface.svector3f = rsurface.array_deformedsvector3f;
6567 rsurface.svector3f_bufferobject = 0;
6568 rsurface.svector3f_bufferoffset = 0;
6569 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6570 rsurface.tvector3f_bufferobject = 0;
6571 rsurface.tvector3f_bufferoffset = 0;
6572 rsurface.normal3f = rsurface.array_deformednormal3f;
6573 rsurface.normal3f_bufferobject = 0;
6574 rsurface.normal3f_bufferoffset = 0;
6576 case Q3DEFORM_NORMAL:
6577 // deform the normals to make reflections wavey
6578 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6580 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6581 for (j = 0;j < surface->num_vertices;j++)
6584 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6585 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6586 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6587 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6588 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6589 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6590 VectorNormalize(normal);
6592 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);
6594 rsurface.svector3f = rsurface.array_deformedsvector3f;
6595 rsurface.svector3f_bufferobject = 0;
6596 rsurface.svector3f_bufferoffset = 0;
6597 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6598 rsurface.tvector3f_bufferobject = 0;
6599 rsurface.tvector3f_bufferoffset = 0;
6600 rsurface.normal3f = rsurface.array_deformednormal3f;
6601 rsurface.normal3f_bufferobject = 0;
6602 rsurface.normal3f_bufferoffset = 0;
6605 // deform vertex array to make wavey water and flags and such
6606 waveparms[0] = deform->waveparms[0];
6607 waveparms[1] = deform->waveparms[1];
6608 waveparms[2] = deform->waveparms[2];
6609 waveparms[3] = deform->waveparms[3];
6610 // this is how a divisor of vertex influence on deformation
6611 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6612 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6613 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6615 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6616 for (j = 0;j < surface->num_vertices;j++)
6618 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6619 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6620 // if the wavefunc depends on time, evaluate it per-vertex
6623 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6624 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6626 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6629 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6630 rsurface.vertex3f_bufferobject = 0;
6631 rsurface.vertex3f_bufferoffset = 0;
6633 case Q3DEFORM_BULGE:
6634 // deform vertex array to make the surface have moving bulges
6635 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6637 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6638 for (j = 0;j < surface->num_vertices;j++)
6640 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6641 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6644 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6645 rsurface.vertex3f_bufferobject = 0;
6646 rsurface.vertex3f_bufferoffset = 0;
6649 // deform vertex array
6650 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6651 VectorScale(deform->parms, scale, waveparms);
6652 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6654 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6655 for (j = 0;j < surface->num_vertices;j++)
6656 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6658 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6659 rsurface.vertex3f_bufferobject = 0;
6660 rsurface.vertex3f_bufferoffset = 0;
6664 // generate texcoords based on the chosen texcoord source
6665 switch(rsurface.texture->tcgen.tcgen)
6668 case Q3TCGEN_TEXTURE:
6669 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6670 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6671 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6673 case Q3TCGEN_LIGHTMAP:
6674 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6675 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6676 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6678 case Q3TCGEN_VECTOR:
6679 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6681 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6682 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)
6684 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6685 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6688 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6689 rsurface.texcoordtexture2f_bufferobject = 0;
6690 rsurface.texcoordtexture2f_bufferoffset = 0;
6692 case Q3TCGEN_ENVIRONMENT:
6693 // make environment reflections using a spheremap
6694 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6696 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6697 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6698 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6699 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6700 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6702 // identical to Q3A's method, but executed in worldspace so
6703 // carried models can be shiny too
6705 float viewer[3], d, reflected[3], worldreflected[3];
6707 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6708 // VectorNormalize(viewer);
6710 d = DotProduct(normal, viewer);
6712 reflected[0] = normal[0]*2*d - viewer[0];
6713 reflected[1] = normal[1]*2*d - viewer[1];
6714 reflected[2] = normal[2]*2*d - viewer[2];
6715 // note: this is proportinal to viewer, so we can normalize later
6717 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6718 VectorNormalize(worldreflected);
6720 // note: this sphere map only uses world x and z!
6721 // so positive and negative y will LOOK THE SAME.
6722 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6723 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6726 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6727 rsurface.texcoordtexture2f_bufferobject = 0;
6728 rsurface.texcoordtexture2f_bufferoffset = 0;
6731 // the only tcmod that needs software vertex processing is turbulent, so
6732 // check for it here and apply the changes if needed
6733 // and we only support that as the first one
6734 // (handling a mixture of turbulent and other tcmods would be problematic
6735 // without punting it entirely to a software path)
6736 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6738 amplitude = rsurface.texture->tcmods[0].parms[1];
6739 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6740 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6742 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6743 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)
6745 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6746 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6749 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6750 rsurface.texcoordtexture2f_bufferobject = 0;
6751 rsurface.texcoordtexture2f_bufferoffset = 0;
6753 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6754 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6755 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6756 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6759 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6762 const msurface_t *surface = texturesurfacelist[0];
6763 const msurface_t *surface2;
6768 // TODO: lock all array ranges before render, rather than on each surface
6769 if (texturenumsurfaces == 1)
6771 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6772 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);
6774 else if (r_batchmode.integer == 2)
6776 #define MAXBATCHTRIANGLES 4096
6777 int batchtriangles = 0;
6778 int batchelements[MAXBATCHTRIANGLES*3];
6779 for (i = 0;i < texturenumsurfaces;i = j)
6781 surface = texturesurfacelist[i];
6783 if (surface->num_triangles > MAXBATCHTRIANGLES)
6785 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);
6788 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6789 batchtriangles = surface->num_triangles;
6790 firstvertex = surface->num_firstvertex;
6791 endvertex = surface->num_firstvertex + surface->num_vertices;
6792 for (;j < texturenumsurfaces;j++)
6794 surface2 = texturesurfacelist[j];
6795 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6797 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6798 batchtriangles += surface2->num_triangles;
6799 firstvertex = min(firstvertex, surface2->num_firstvertex);
6800 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6802 surface2 = texturesurfacelist[j-1];
6803 numvertices = endvertex - firstvertex;
6804 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6807 else if (r_batchmode.integer == 1)
6809 for (i = 0;i < texturenumsurfaces;i = j)
6811 surface = texturesurfacelist[i];
6812 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6813 if (texturesurfacelist[j] != surface2)
6815 surface2 = texturesurfacelist[j-1];
6816 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6817 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6818 GL_LockArrays(surface->num_firstvertex, numvertices);
6819 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6824 for (i = 0;i < texturenumsurfaces;i++)
6826 surface = texturesurfacelist[i];
6827 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6828 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);
6833 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6835 int i, planeindex, vertexindex;
6839 r_waterstate_waterplane_t *p, *bestp;
6840 const msurface_t *surface;
6841 if (r_waterstate.renderingscene)
6843 for (i = 0;i < texturenumsurfaces;i++)
6845 surface = texturesurfacelist[i];
6846 if (lightmaptexunit >= 0)
6847 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6848 if (deluxemaptexunit >= 0)
6849 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6850 // pick the closest matching water plane
6853 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6856 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6858 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6859 d += fabs(PlaneDiff(vert, &p->plane));
6861 if (bestd > d || !bestp)
6869 if (refractiontexunit >= 0)
6870 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6871 if (reflectiontexunit >= 0)
6872 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6876 if (refractiontexunit >= 0)
6877 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6878 if (reflectiontexunit >= 0)
6879 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6881 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6882 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);
6886 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6890 const msurface_t *surface = texturesurfacelist[0];
6891 const msurface_t *surface2;
6896 // TODO: lock all array ranges before render, rather than on each surface
6897 if (texturenumsurfaces == 1)
6899 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6900 if (deluxemaptexunit >= 0)
6901 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6902 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6903 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6905 else if (r_batchmode.integer == 2)
6907 #define MAXBATCHTRIANGLES 4096
6908 int batchtriangles = 0;
6909 int batchelements[MAXBATCHTRIANGLES*3];
6910 for (i = 0;i < texturenumsurfaces;i = j)
6912 surface = texturesurfacelist[i];
6913 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6914 if (deluxemaptexunit >= 0)
6915 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6917 if (surface->num_triangles > MAXBATCHTRIANGLES)
6919 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);
6922 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6923 batchtriangles = surface->num_triangles;
6924 firstvertex = surface->num_firstvertex;
6925 endvertex = surface->num_firstvertex + surface->num_vertices;
6926 for (;j < texturenumsurfaces;j++)
6928 surface2 = texturesurfacelist[j];
6929 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6931 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6932 batchtriangles += surface2->num_triangles;
6933 firstvertex = min(firstvertex, surface2->num_firstvertex);
6934 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6936 surface2 = texturesurfacelist[j-1];
6937 numvertices = endvertex - firstvertex;
6938 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6941 else if (r_batchmode.integer == 1)
6944 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6945 for (i = 0;i < texturenumsurfaces;i = j)
6947 surface = texturesurfacelist[i];
6948 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6949 if (texturesurfacelist[j] != surface2)
6951 Con_Printf(" %i", j - i);
6954 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6956 for (i = 0;i < texturenumsurfaces;i = j)
6958 surface = texturesurfacelist[i];
6959 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6960 if (deluxemaptexunit >= 0)
6961 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6962 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6963 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6966 Con_Printf(" %i", j - i);
6968 surface2 = texturesurfacelist[j-1];
6969 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6970 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6971 GL_LockArrays(surface->num_firstvertex, numvertices);
6972 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6980 for (i = 0;i < texturenumsurfaces;i++)
6982 surface = texturesurfacelist[i];
6983 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6984 if (deluxemaptexunit >= 0)
6985 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6986 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6987 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);
6992 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6995 int texturesurfaceindex;
6996 if (r_showsurfaces.integer == 2)
6998 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7000 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7001 for (j = 0;j < surface->num_triangles;j++)
7003 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7004 GL_Color(f, f, f, 1);
7005 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7011 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7013 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7014 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7015 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);
7016 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7017 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);
7022 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7024 int texturesurfaceindex;
7028 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7030 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7031 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)
7039 rsurface.lightmapcolor4f = rsurface.array_color4f;
7040 rsurface.lightmapcolor4f_bufferobject = 0;
7041 rsurface.lightmapcolor4f_bufferoffset = 0;
7044 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7046 int texturesurfaceindex;
7052 if (rsurface.lightmapcolor4f)
7054 // generate color arrays for the surfaces in this list
7055 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7057 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7058 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)
7060 f = RSurf_FogVertex(v);
7070 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7072 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7073 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)
7075 f = RSurf_FogVertex(v);
7083 rsurface.lightmapcolor4f = rsurface.array_color4f;
7084 rsurface.lightmapcolor4f_bufferobject = 0;
7085 rsurface.lightmapcolor4f_bufferoffset = 0;
7088 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7090 int texturesurfaceindex;
7096 if (!rsurface.lightmapcolor4f)
7098 // generate color arrays for the surfaces in this list
7099 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7101 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7102 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)
7104 f = RSurf_FogVertex(v);
7105 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7106 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7107 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7111 rsurface.lightmapcolor4f = rsurface.array_color4f;
7112 rsurface.lightmapcolor4f_bufferobject = 0;
7113 rsurface.lightmapcolor4f_bufferoffset = 0;
7116 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7118 int texturesurfaceindex;
7122 if (!rsurface.lightmapcolor4f)
7124 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7126 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7127 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)
7135 rsurface.lightmapcolor4f = rsurface.array_color4f;
7136 rsurface.lightmapcolor4f_bufferobject = 0;
7137 rsurface.lightmapcolor4f_bufferoffset = 0;
7140 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7142 int texturesurfaceindex;
7146 if (!rsurface.lightmapcolor4f)
7148 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7150 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7151 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)
7153 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7154 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7155 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7159 rsurface.lightmapcolor4f = rsurface.array_color4f;
7160 rsurface.lightmapcolor4f_bufferobject = 0;
7161 rsurface.lightmapcolor4f_bufferoffset = 0;
7164 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7167 rsurface.lightmapcolor4f = NULL;
7168 rsurface.lightmapcolor4f_bufferobject = 0;
7169 rsurface.lightmapcolor4f_bufferoffset = 0;
7170 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7171 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7172 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7173 GL_Color(r, g, b, a);
7174 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7177 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7179 // TODO: optimize applyfog && applycolor case
7180 // just apply fog if necessary, and tint the fog color array if necessary
7181 rsurface.lightmapcolor4f = NULL;
7182 rsurface.lightmapcolor4f_bufferobject = 0;
7183 rsurface.lightmapcolor4f_bufferoffset = 0;
7184 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7185 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7186 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7187 GL_Color(r, g, b, a);
7188 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7191 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7193 int texturesurfaceindex;
7197 if (texturesurfacelist[0]->lightmapinfo)
7199 // generate color arrays for the surfaces in this list
7200 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7202 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7203 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7205 if (surface->lightmapinfo->samples)
7207 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7208 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7209 VectorScale(lm, scale, c);
7210 if (surface->lightmapinfo->styles[1] != 255)
7212 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7214 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7215 VectorMA(c, scale, lm, c);
7216 if (surface->lightmapinfo->styles[2] != 255)
7219 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7220 VectorMA(c, scale, lm, c);
7221 if (surface->lightmapinfo->styles[3] != 255)
7224 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7225 VectorMA(c, scale, lm, c);
7235 rsurface.lightmapcolor4f = rsurface.array_color4f;
7236 rsurface.lightmapcolor4f_bufferobject = 0;
7237 rsurface.lightmapcolor4f_bufferoffset = 0;
7241 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7242 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7243 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7245 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7246 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7247 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7248 GL_Color(r, g, b, a);
7249 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7252 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7254 int texturesurfaceindex;
7261 vec3_t ambientcolor;
7262 vec3_t diffusecolor;
7266 VectorCopy(rsurface.modellight_lightdir, lightdir);
7267 f = 0.5f * r_refdef.lightmapintensity;
7268 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7269 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7270 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7271 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7272 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7273 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7275 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7277 // generate color arrays for the surfaces in this list
7278 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7280 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7281 int numverts = surface->num_vertices;
7282 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7283 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7284 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7285 // q3-style directional shading
7286 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7288 if ((f = DotProduct(n, lightdir)) > 0)
7289 VectorMA(ambientcolor, f, diffusecolor, c);
7291 VectorCopy(ambientcolor, c);
7299 rsurface.lightmapcolor4f = rsurface.array_color4f;
7300 rsurface.lightmapcolor4f_bufferobject = 0;
7301 rsurface.lightmapcolor4f_bufferoffset = 0;
7302 *applycolor = false;
7306 *r = ambientcolor[0];
7307 *g = ambientcolor[1];
7308 *b = ambientcolor[2];
7309 rsurface.lightmapcolor4f = NULL;
7310 rsurface.lightmapcolor4f_bufferobject = 0;
7311 rsurface.lightmapcolor4f_bufferoffset = 0;
7315 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7317 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7318 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7319 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7320 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7321 GL_Color(r, g, b, a);
7322 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7325 void RSurf_SetupDepthAndCulling(void)
7327 // submodels are biased to avoid z-fighting with world surfaces that they
7328 // may be exactly overlapping (avoids z-fighting artifacts on certain
7329 // doors and things in Quake maps)
7330 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7331 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7332 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7333 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7336 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7338 // transparent sky would be ridiculous
7339 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7341 R_SetupGenericShader(false);
7342 skyrenderlater = true;
7343 RSurf_SetupDepthAndCulling();
7345 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7346 // skymasking on them, and Quake3 never did sky masking (unlike
7347 // software Quake and software Quake2), so disable the sky masking
7348 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7349 // and skymasking also looks very bad when noclipping outside the
7350 // level, so don't use it then either.
7351 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7353 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7354 R_Mesh_ColorPointer(NULL, 0, 0);
7355 R_Mesh_ResetTextureState();
7356 if (skyrendermasked)
7358 R_SetupDepthOrShadowShader();
7359 // depth-only (masking)
7360 GL_ColorMask(0,0,0,0);
7361 // just to make sure that braindead drivers don't draw
7362 // anything despite that colormask...
7363 GL_BlendFunc(GL_ZERO, GL_ONE);
7367 R_SetupGenericShader(false);
7369 GL_BlendFunc(GL_ONE, GL_ZERO);
7371 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7372 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7373 if (skyrendermasked)
7374 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7376 R_Mesh_ResetTextureState();
7377 GL_Color(1, 1, 1, 1);
7380 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7382 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7385 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7386 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7387 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7388 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7389 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7390 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7391 if (rsurface.texture->backgroundcurrentskinframe)
7393 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7394 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7395 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7396 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7398 if(rsurface.texture->colormapping)
7400 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7401 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7403 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7404 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7405 R_Mesh_ColorPointer(NULL, 0, 0);
7407 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7409 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7411 // render background
7412 GL_BlendFunc(GL_ONE, GL_ZERO);
7414 GL_AlphaTest(false);
7416 GL_Color(1, 1, 1, 1);
7417 R_Mesh_ColorPointer(NULL, 0, 0);
7419 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7420 if (r_glsl_permutation)
7422 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7423 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7424 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7425 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7426 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7427 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7428 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);
7430 GL_LockArrays(0, 0);
7432 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7433 GL_DepthMask(false);
7434 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7435 R_Mesh_ColorPointer(NULL, 0, 0);
7437 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7438 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7439 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7442 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7443 if (!r_glsl_permutation)
7446 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7447 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7448 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7449 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7450 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7451 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7453 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7455 GL_BlendFunc(GL_ONE, GL_ZERO);
7457 GL_AlphaTest(false);
7461 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7462 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7463 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7466 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7468 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7469 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);
7471 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7475 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7476 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
7478 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7480 GL_LockArrays(0, 0);
7483 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7485 // OpenGL 1.3 path - anything not completely ancient
7486 int texturesurfaceindex;
7487 qboolean applycolor;
7491 const texturelayer_t *layer;
7492 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7494 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7497 int layertexrgbscale;
7498 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7500 if (layerindex == 0)
7504 GL_AlphaTest(false);
7505 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7508 GL_DepthMask(layer->depthmask && writedepth);
7509 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7510 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7512 layertexrgbscale = 4;
7513 VectorScale(layer->color, 0.25f, layercolor);
7515 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7517 layertexrgbscale = 2;
7518 VectorScale(layer->color, 0.5f, layercolor);
7522 layertexrgbscale = 1;
7523 VectorScale(layer->color, 1.0f, layercolor);
7525 layercolor[3] = layer->color[3];
7526 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7527 R_Mesh_ColorPointer(NULL, 0, 0);
7528 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7529 switch (layer->type)
7531 case TEXTURELAYERTYPE_LITTEXTURE:
7532 memset(&m, 0, sizeof(m));
7533 m.tex[0] = R_GetTexture(r_texture_white);
7534 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7535 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7536 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7537 m.tex[1] = R_GetTexture(layer->texture);
7538 m.texmatrix[1] = layer->texmatrix;
7539 m.texrgbscale[1] = layertexrgbscale;
7540 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7541 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7542 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7543 R_Mesh_TextureState(&m);
7544 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7545 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7546 else if (rsurface.uselightmaptexture)
7547 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7549 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7551 case TEXTURELAYERTYPE_TEXTURE:
7552 memset(&m, 0, sizeof(m));
7553 m.tex[0] = R_GetTexture(layer->texture);
7554 m.texmatrix[0] = layer->texmatrix;
7555 m.texrgbscale[0] = layertexrgbscale;
7556 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7557 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7558 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7559 R_Mesh_TextureState(&m);
7560 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7562 case TEXTURELAYERTYPE_FOG:
7563 memset(&m, 0, sizeof(m));
7564 m.texrgbscale[0] = layertexrgbscale;
7567 m.tex[0] = R_GetTexture(layer->texture);
7568 m.texmatrix[0] = layer->texmatrix;
7569 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7570 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7571 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7573 R_Mesh_TextureState(&m);
7574 // generate a color array for the fog pass
7575 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7576 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7582 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7583 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)
7585 f = 1 - RSurf_FogVertex(v);
7586 c[0] = layercolor[0];
7587 c[1] = layercolor[1];
7588 c[2] = layercolor[2];
7589 c[3] = f * layercolor[3];
7592 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7595 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7597 GL_LockArrays(0, 0);
7600 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7602 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7603 GL_AlphaTest(false);
7607 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7609 // OpenGL 1.1 - crusty old voodoo path
7610 int texturesurfaceindex;
7614 const texturelayer_t *layer;
7615 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7617 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7619 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7621 if (layerindex == 0)
7625 GL_AlphaTest(false);
7626 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7629 GL_DepthMask(layer->depthmask && writedepth);
7630 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7631 R_Mesh_ColorPointer(NULL, 0, 0);
7632 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7633 switch (layer->type)
7635 case TEXTURELAYERTYPE_LITTEXTURE:
7636 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7638 // two-pass lit texture with 2x rgbscale
7639 // first the lightmap pass
7640 memset(&m, 0, sizeof(m));
7641 m.tex[0] = R_GetTexture(r_texture_white);
7642 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7643 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7644 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7645 R_Mesh_TextureState(&m);
7646 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7647 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7648 else if (rsurface.uselightmaptexture)
7649 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7651 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7652 GL_LockArrays(0, 0);
7653 // then apply the texture to it
7654 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7655 memset(&m, 0, sizeof(m));
7656 m.tex[0] = R_GetTexture(layer->texture);
7657 m.texmatrix[0] = layer->texmatrix;
7658 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7659 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7660 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7661 R_Mesh_TextureState(&m);
7662 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);
7666 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7667 memset(&m, 0, sizeof(m));
7668 m.tex[0] = R_GetTexture(layer->texture);
7669 m.texmatrix[0] = layer->texmatrix;
7670 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7671 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7672 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7673 R_Mesh_TextureState(&m);
7674 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7675 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);
7677 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);
7680 case TEXTURELAYERTYPE_TEXTURE:
7681 // singletexture unlit texture with transparency support
7682 memset(&m, 0, sizeof(m));
7683 m.tex[0] = R_GetTexture(layer->texture);
7684 m.texmatrix[0] = layer->texmatrix;
7685 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7686 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7687 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7688 R_Mesh_TextureState(&m);
7689 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);
7691 case TEXTURELAYERTYPE_FOG:
7692 // singletexture fogging
7693 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7696 memset(&m, 0, sizeof(m));
7697 m.tex[0] = R_GetTexture(layer->texture);
7698 m.texmatrix[0] = layer->texmatrix;
7699 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7700 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7701 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7702 R_Mesh_TextureState(&m);
7705 R_Mesh_ResetTextureState();
7706 // generate a color array for the fog pass
7707 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7713 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7714 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)
7716 f = 1 - RSurf_FogVertex(v);
7717 c[0] = layer->color[0];
7718 c[1] = layer->color[1];
7719 c[2] = layer->color[2];
7720 c[3] = f * layer->color[3];
7723 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7726 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7728 GL_LockArrays(0, 0);
7731 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7733 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7734 GL_AlphaTest(false);
7738 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7742 GL_AlphaTest(false);
7743 R_Mesh_ColorPointer(NULL, 0, 0);
7744 R_Mesh_ResetTextureState();
7745 R_SetupGenericShader(false);
7747 if(rsurface.texture && rsurface.texture->currentskinframe)
7749 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7750 c[3] *= rsurface.texture->currentalpha;
7760 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7762 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7763 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7764 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7767 // brighten it up (as texture value 127 means "unlit")
7768 c[0] *= 2 * r_refdef.view.colorscale;
7769 c[1] *= 2 * r_refdef.view.colorscale;
7770 c[2] *= 2 * r_refdef.view.colorscale;
7772 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7773 c[3] *= r_wateralpha.value;
7775 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7777 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7778 GL_DepthMask(false);
7780 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7782 GL_BlendFunc(GL_ONE, GL_ONE);
7783 GL_DepthMask(false);
7785 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7787 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7788 GL_DepthMask(false);
7790 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7792 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7793 GL_DepthMask(false);
7797 GL_BlendFunc(GL_ONE, GL_ZERO);
7798 GL_DepthMask(writedepth);
7801 rsurface.lightmapcolor4f = NULL;
7803 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7805 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7807 rsurface.lightmapcolor4f = NULL;
7808 rsurface.lightmapcolor4f_bufferobject = 0;
7809 rsurface.lightmapcolor4f_bufferoffset = 0;
7811 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7813 qboolean applycolor = true;
7816 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7818 r_refdef.lightmapintensity = 1;
7819 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7820 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7824 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7826 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7827 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7828 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7831 if(!rsurface.lightmapcolor4f)
7832 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7834 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7835 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7836 if(r_refdef.fogenabled)
7837 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7839 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7840 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7843 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7846 RSurf_SetupDepthAndCulling();
7847 if (r_showsurfaces.integer == 3)
7848 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7849 else if (r_glsl.integer && gl_support_fragment_shader)
7850 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7851 else if (gl_combine.integer && r_textureunits.integer >= 2)
7852 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7854 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7858 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7861 RSurf_SetupDepthAndCulling();
7862 if (r_showsurfaces.integer == 3)
7863 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7864 else if (r_glsl.integer && gl_support_fragment_shader)
7865 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7866 else if (gl_combine.integer && r_textureunits.integer >= 2)
7867 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7869 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7873 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7876 int texturenumsurfaces, endsurface;
7878 const msurface_t *surface;
7879 const msurface_t *texturesurfacelist[1024];
7881 // if the model is static it doesn't matter what value we give for
7882 // wantnormals and wanttangents, so this logic uses only rules applicable
7883 // to a model, knowing that they are meaningless otherwise
7884 if (ent == r_refdef.scene.worldentity)
7885 RSurf_ActiveWorldEntity();
7886 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7887 RSurf_ActiveModelEntity(ent, false, false);
7889 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7891 for (i = 0;i < numsurfaces;i = j)
7894 surface = rsurface.modelsurfaces + surfacelist[i];
7895 texture = surface->texture;
7896 rsurface.texture = R_GetCurrentTexture(texture);
7897 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7898 // scan ahead until we find a different texture
7899 endsurface = min(i + 1024, numsurfaces);
7900 texturenumsurfaces = 0;
7901 texturesurfacelist[texturenumsurfaces++] = surface;
7902 for (;j < endsurface;j++)
7904 surface = rsurface.modelsurfaces + surfacelist[j];
7905 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7907 texturesurfacelist[texturenumsurfaces++] = surface;
7909 // render the range of surfaces
7910 if (ent == r_refdef.scene.worldentity)
7911 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7913 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7915 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7916 GL_AlphaTest(false);
7919 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7921 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7925 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7927 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7929 RSurf_SetupDepthAndCulling();
7930 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7931 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7933 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7935 RSurf_SetupDepthAndCulling();
7936 GL_AlphaTest(false);
7937 R_Mesh_ColorPointer(NULL, 0, 0);
7938 R_Mesh_ResetTextureState();
7939 R_SetupGenericShader(false);
7940 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7942 GL_BlendFunc(GL_ONE, GL_ZERO);
7943 GL_Color(0, 0, 0, 1);
7944 GL_DepthTest(writedepth);
7945 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7947 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7949 RSurf_SetupDepthAndCulling();
7950 GL_AlphaTest(false);
7951 R_Mesh_ColorPointer(NULL, 0, 0);
7952 R_Mesh_ResetTextureState();
7953 R_SetupGenericShader(false);
7954 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7956 GL_BlendFunc(GL_ONE, GL_ZERO);
7958 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7960 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7961 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7962 else if (!rsurface.texture->currentnumlayers)
7964 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7966 // transparent surfaces get pushed off into the transparent queue
7967 int surfacelistindex;
7968 const msurface_t *surface;
7969 vec3_t tempcenter, center;
7970 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7972 surface = texturesurfacelist[surfacelistindex];
7973 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7974 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7975 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7976 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7977 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7982 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7983 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7988 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7992 // break the surface list down into batches by texture and use of lightmapping
7993 for (i = 0;i < numsurfaces;i = j)
7996 // texture is the base texture pointer, rsurface.texture is the
7997 // current frame/skin the texture is directing us to use (for example
7998 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7999 // use skin 1 instead)
8000 texture = surfacelist[i]->texture;
8001 rsurface.texture = R_GetCurrentTexture(texture);
8002 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8003 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8005 // if this texture is not the kind we want, skip ahead to the next one
8006 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8010 // simply scan ahead until we find a different texture or lightmap state
8011 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8013 // render the range of surfaces
8014 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
8018 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
8023 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8025 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8027 RSurf_SetupDepthAndCulling();
8028 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8029 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8031 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8033 RSurf_SetupDepthAndCulling();
8034 GL_AlphaTest(false);
8035 R_Mesh_ColorPointer(NULL, 0, 0);
8036 R_Mesh_ResetTextureState();
8037 R_SetupGenericShader(false);
8038 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8040 GL_BlendFunc(GL_ONE, GL_ZERO);
8041 GL_Color(0, 0, 0, 1);
8042 GL_DepthTest(writedepth);
8043 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8045 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8047 RSurf_SetupDepthAndCulling();
8048 GL_AlphaTest(false);
8049 R_Mesh_ColorPointer(NULL, 0, 0);
8050 R_Mesh_ResetTextureState();
8051 R_SetupGenericShader(false);
8052 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8054 GL_BlendFunc(GL_ONE, GL_ZERO);
8056 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8058 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8059 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8060 else if (!rsurface.texture->currentnumlayers)
8062 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8064 // transparent surfaces get pushed off into the transparent queue
8065 int surfacelistindex;
8066 const msurface_t *surface;
8067 vec3_t tempcenter, center;
8068 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8070 surface = texturesurfacelist[surfacelistindex];
8071 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8072 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8073 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8074 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8075 if (queueentity->transparent_offset) // transparent offset
8077 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8078 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8079 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8081 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8086 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8087 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8092 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8096 // break the surface list down into batches by texture and use of lightmapping
8097 for (i = 0;i < numsurfaces;i = j)
8100 // texture is the base texture pointer, rsurface.texture is the
8101 // current frame/skin the texture is directing us to use (for example
8102 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8103 // use skin 1 instead)
8104 texture = surfacelist[i]->texture;
8105 rsurface.texture = R_GetCurrentTexture(texture);
8106 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8107 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8109 // if this texture is not the kind we want, skip ahead to the next one
8110 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8114 // simply scan ahead until we find a different texture or lightmap state
8115 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8117 // render the range of surfaces
8118 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8122 float locboxvertex3f[6*4*3] =
8124 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8125 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8126 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8127 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8128 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8129 1,0,0, 0,0,0, 0,1,0, 1,1,0
8132 unsigned short locboxelements[6*2*3] =
8142 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8145 cl_locnode_t *loc = (cl_locnode_t *)ent;
8147 float vertex3f[6*4*3];
8149 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8150 GL_DepthMask(false);
8151 GL_DepthRange(0, 1);
8152 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8154 GL_CullFace(GL_NONE);
8155 R_Mesh_Matrix(&identitymatrix);
8157 R_Mesh_VertexPointer(vertex3f, 0, 0);
8158 R_Mesh_ColorPointer(NULL, 0, 0);
8159 R_Mesh_ResetTextureState();
8160 R_SetupGenericShader(false);
8163 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8164 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8165 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8166 surfacelist[0] < 0 ? 0.5f : 0.125f);
8168 if (VectorCompare(loc->mins, loc->maxs))
8170 VectorSet(size, 2, 2, 2);
8171 VectorMA(loc->mins, -0.5f, size, mins);
8175 VectorCopy(loc->mins, mins);
8176 VectorSubtract(loc->maxs, loc->mins, size);
8179 for (i = 0;i < 6*4*3;)
8180 for (j = 0;j < 3;j++, i++)
8181 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8183 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8186 void R_DrawLocs(void)
8189 cl_locnode_t *loc, *nearestloc;
8191 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8192 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8194 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8195 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8199 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8201 if (decalsystem->decals)
8202 Mem_Free(decalsystem->decals);
8203 memset(decalsystem, 0, sizeof(*decalsystem));
8206 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)
8217 // expand or initialize the system
8218 if (decalsystem->maxdecals <= decalsystem->numdecals)
8220 decalsystem_t old = *decalsystem;
8221 qboolean useshortelements;
8222 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8223 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8224 decalsystem->decals = Mem_Alloc(cls.levelmempool, decalsystem->maxdecals * (sizeof(tridecal_t) + sizeof(float[3][3]) + sizeof(float[3][2]) + sizeof(float[3][4]) + sizeof(int[3]) + (useshortelements ? sizeof(unsigned short[3]) : 0)));
8225 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8226 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8227 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8228 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8229 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8230 if (decalsystem->numdecals)
8232 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8233 memcpy(decalsystem->vertex3f, old.vertex3f, decalsystem->numdecals * sizeof(float[3][3]));
8234 memcpy(decalsystem->texcoord2f, old.texcoord2f, decalsystem->numdecals * sizeof(float[3][2]));
8235 memcpy(decalsystem->color4f, old.color4f, decalsystem->numdecals * sizeof(float[3][4]));
8237 Mem_Free(old.decals);
8238 for (i = 0;i < decalsystem->maxdecals*3;i++)
8239 decalsystem->element3i[i] = i;
8240 if (useshortelements)
8241 for (i = 0;i < decalsystem->maxdecals*3;i++)
8242 decalsystem->element3s[i] = i;
8245 // grab a decal and search for another free slot for the next one
8246 maxdecals = decalsystem->maxdecals;
8247 decals = decalsystem->decals;
8248 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8249 v3f = decalsystem->vertex3f + 9*i;
8250 tc2f = decalsystem->texcoord2f + 6*i;
8251 c4f = decalsystem->color4f + 12*i;
8252 for (i = decalsystem->freedecal;i < maxdecals && decals[i].colors[0][3];i++)
8254 decalsystem->freedecal = i;
8255 if (decalsystem->numdecals <= i)
8256 decalsystem->numdecals = i + 1;
8258 // initialize the decal
8260 decal->triangleindex = triangleindex;
8261 decal->colors[0][0] = (unsigned char)(c0[0]*255.0f);
8262 decal->colors[0][1] = (unsigned char)(c0[1]*255.0f);
8263 decal->colors[0][2] = (unsigned char)(c0[2]*255.0f);
8264 decal->colors[0][3] = 255;
8265 decal->colors[1][0] = (unsigned char)(c1[0]*255.0f);
8266 decal->colors[1][1] = (unsigned char)(c1[1]*255.0f);
8267 decal->colors[1][2] = (unsigned char)(c1[2]*255.0f);
8268 decal->colors[1][3] = 255;
8269 decal->colors[2][0] = (unsigned char)(c2[0]*255.0f);
8270 decal->colors[2][1] = (unsigned char)(c2[1]*255.0f);
8271 decal->colors[2][2] = (unsigned char)(c2[2]*255.0f);
8272 decal->colors[2][3] = 255;
8289 c4f[ 0] = decal->colors[0][0] * ca;
8290 c4f[ 1] = decal->colors[0][1] * ca;
8291 c4f[ 2] = decal->colors[0][2] * ca;
8293 c4f[ 4] = decal->colors[1][0] * ca;
8294 c4f[ 5] = decal->colors[1][1] * ca;
8295 c4f[ 6] = decal->colors[1][2] * ca;
8297 c4f[ 8] = decal->colors[2][0] * ca;
8298 c4f[ 9] = decal->colors[2][1] * ca;
8299 c4f[10] = decal->colors[2][2] * ca;
8303 extern cvar_t cl_decals_bias;
8304 extern cvar_t cl_decals_models;
8305 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)
8307 matrix4x4_t projection;
8308 decalsystem_t *decalsystem;
8311 const float *vertex3f;
8312 const msurface_t *surface;
8313 const msurface_t *surfaces;
8314 const int *surfacelist;
8315 const texture_t *texture;
8319 int surfacelistindex;
8325 float localorigin[3];
8326 float localnormal[3];
8337 float points[2][9][3];
8341 decalsystem = &ent->decalsystem;
8343 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8345 R_DecalSystem_Reset(&ent->decalsystem);
8349 if (!model->brush.data_nodes && !cl_decals_models.integer)
8351 if (decalsystem->model)
8352 R_DecalSystem_Reset(decalsystem);
8356 if (decalsystem->model != model)
8357 R_DecalSystem_Reset(decalsystem);
8358 decalsystem->model = model;
8360 RSurf_ActiveModelEntity(ent, false, false);
8362 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8363 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8364 VectorNormalize(localnormal);
8365 localsize = worldsize*rsurface.inversematrixscale;
8366 ilocalsize = 1.0f / localsize;
8367 localmins[0] = localorigin[0] - localsize;
8368 localmins[1] = localorigin[1] - localsize;
8369 localmins[2] = localorigin[2] - localsize;
8370 localmaxs[0] = localorigin[0] + localsize;
8371 localmaxs[1] = localorigin[1] + localsize;
8372 localmaxs[2] = localorigin[2] + localsize;
8374 //VectorCopy(localnormal, planes[4]);
8375 //VectorVectors(planes[4], planes[2], planes[0]);
8376 AnglesFromVectors(angles, localnormal, NULL, false);
8377 AngleVectors(angles, planes[0], planes[2], planes[4]);
8378 VectorNegate(planes[0], planes[1]);
8379 VectorNegate(planes[2], planes[3]);
8380 VectorNegate(planes[4], planes[5]);
8381 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8382 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8383 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8384 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8385 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8386 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8391 matrix4x4_t forwardprojection;
8392 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8393 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8398 float projectionvector[4][3];
8399 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8400 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8401 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8402 projectionvector[0][0] = planes[0][0] * ilocalsize;
8403 projectionvector[0][1] = planes[1][0] * ilocalsize;
8404 projectionvector[0][2] = planes[2][0] * ilocalsize;
8405 projectionvector[1][0] = planes[0][1] * ilocalsize;
8406 projectionvector[1][1] = planes[1][1] * ilocalsize;
8407 projectionvector[1][2] = planes[2][1] * ilocalsize;
8408 projectionvector[2][0] = planes[0][2] * ilocalsize;
8409 projectionvector[2][1] = planes[1][2] * ilocalsize;
8410 projectionvector[2][2] = planes[2][2] * ilocalsize;
8411 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8412 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8413 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8414 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8418 dynamic = model->surfmesh.isanimated;
8419 vertex3f = rsurface.modelvertex3f;
8420 numsurfacelist = model->nummodelsurfaces;
8421 surfacelist = model->sortedmodelsurfaces;
8422 surfaces = model->data_surfaces;
8423 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8425 surface = surfaces + surfacelist[surfacelistindex];
8426 // skip transparent surfaces
8427 texture = surface->texture;
8428 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8430 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8432 if (texture->currentalpha < 1)
8434 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8436 numvertices = surface->num_vertices;
8437 numtriangles = surface->num_triangles;
8438 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8440 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8442 index = 3*e[cornerindex];
8443 VectorCopy(vertex3f + index, v[cornerindex]);
8446 //TriangleNormal(v[0], v[1], v[2], normal);
8447 //if (DotProduct(normal, localnormal) < 0.0f)
8449 // clip by each of the box planes formed from the projection matrix
8450 // if anything survives, we emit the decal
8451 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]);
8454 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]);
8457 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]);
8460 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]);
8463 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]);
8466 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]);
8469 // some part of the triangle survived, so we have to accept it...
8472 // dynamic always uses the original triangle
8474 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8476 index = 3*e[cornerindex];
8477 VectorCopy(vertex3f + index, v[cornerindex]);
8480 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8482 // convert vertex positions to texcoords
8483 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8484 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8485 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8486 // calculate distance fade from the projection origin
8487 f = a * (1.0f-fabs(temp[0]));
8489 c[cornerindex][0] = r * f;
8490 c[cornerindex][1] = g * f;
8491 c[cornerindex][2] = b * f;
8492 c[cornerindex][3] = 1.0f;
8493 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8496 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex);
8498 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8499 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);
8504 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)
8506 int renderentityindex;
8509 entity_render_t *ent;
8511 worldmins[0] = worldorigin[0] - worldsize;
8512 worldmins[1] = worldorigin[1] - worldsize;
8513 worldmins[2] = worldorigin[2] - worldsize;
8514 worldmaxs[0] = worldorigin[0] + worldsize;
8515 worldmaxs[1] = worldorigin[1] + worldsize;
8516 worldmaxs[2] = worldorigin[2] + worldsize;
8518 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8520 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8522 ent = r_refdef.scene.entities[renderentityindex];
8523 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8526 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8530 extern skinframe_t *decalskinframe;
8531 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8534 decalsystem_t *decalsystem = &ent->decalsystem;
8545 if (!decalsystem->numdecals)
8548 if (r_showsurfaces.integer)
8551 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8553 R_DecalSystem_Reset(decalsystem);
8557 // if the model is static it doesn't matter what value we give for
8558 // wantnormals and wanttangents, so this logic uses only rules applicable
8559 // to a model, knowing that they are meaningless otherwise
8560 if (ent == r_refdef.scene.worldentity)
8561 RSurf_ActiveWorldEntity();
8563 RSurf_ActiveModelEntity(ent, false, false);
8565 if (decalsystem->lastupdatetime)
8566 frametime = cl.time - decalsystem->lastupdatetime;
8569 decalsystem->lastupdatetime = cl.time;
8570 decal = decalsystem->decals;
8571 numdecals = decalsystem->numdecals;
8573 fadedelay = cl_decals_time.value;
8574 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
8576 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8578 if (!decal->colors[0][3])
8581 decal->lived += frametime;
8582 if (decal->lived >= fadedelay)
8584 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
8587 // kill the decal by zeroing vertex data
8588 memset(decalsystem->vertex3f + 9*i, 0, sizeof(float[3][3]));
8589 memset(decalsystem->texcoord2f + 6*i, 0, sizeof(float[3][2]));
8590 memset(decalsystem->color4f + 12*i, 0, sizeof(float[3][4]));
8591 memset(decal, 0, sizeof(*decal));
8592 if (decalsystem->freedecal > i)
8593 decalsystem->freedecal = i;
8597 // update color values for fading decals
8598 alpha *= (1.0f/255.0f);
8599 c4f = decalsystem->color4f + 12*i;
8600 c4f[ 0] = decal->colors[0][0] * alpha;
8601 c4f[ 1] = decal->colors[0][1] * alpha;
8602 c4f[ 2] = decal->colors[0][2] * alpha;
8604 c4f[ 4] = decal->colors[1][0] * alpha;
8605 c4f[ 5] = decal->colors[1][1] * alpha;
8606 c4f[ 6] = decal->colors[1][2] * alpha;
8608 c4f[ 8] = decal->colors[2][0] * alpha;
8609 c4f[ 9] = decal->colors[2][1] * alpha;
8610 c4f[10] = decal->colors[2][2] * alpha;
8614 // update vertex positions for animated models
8615 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8617 e = rsurface.modelelement3i + 3*decal->triangleindex;
8618 v3f = decalsystem->vertex3f + 9*i;
8619 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8620 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8621 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8625 // reduce numdecals if possible
8626 while (numdecals > 0 && !decalsystem->decals[numdecals - 1].colors[0][3])
8628 decalsystem->numdecals = numdecals;
8632 r_refdef.stats.decals += numdecals;
8633 // now render the decals all at once
8634 // (this assumes they all use one particle font texture!)
8635 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);
8636 R_Mesh_ResetTextureState();
8637 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8638 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8639 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8640 R_SetupGenericShader(true);
8641 GL_DepthMask(false);
8642 GL_DepthRange(0, 1);
8643 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
8645 GL_CullFace(GL_NONE);
8646 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8647 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8648 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8649 GL_LockArrays(0, numdecals * 3);
8650 R_Mesh_Draw(0, numdecals * 3, 0, numdecals, decalsystem->element3i, decalsystem->element3s, 0, 0);
8651 GL_LockArrays(0, 0);
8656 // if there are no decals left, reset decalsystem
8657 R_DecalSystem_Reset(decalsystem);
8661 void R_DrawDebugModel(void)
8663 entity_render_t *ent = rsurface.entity;
8664 int i, j, k, l, flagsmask;
8665 const int *elements;
8667 const msurface_t *surface;
8668 dp_model_t *model = ent->model;
8671 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8673 R_Mesh_ColorPointer(NULL, 0, 0);
8674 R_Mesh_ResetTextureState();
8675 R_SetupGenericShader(false);
8676 GL_DepthRange(0, 1);
8677 GL_DepthTest(!r_showdisabledepthtest.integer);
8678 GL_DepthMask(false);
8679 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8681 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8683 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8684 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8686 if (brush->colbrushf && brush->colbrushf->numtriangles)
8688 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8689 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);
8690 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8693 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8695 if (surface->num_collisiontriangles)
8697 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8698 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);
8699 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8704 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8706 if (r_showtris.integer || r_shownormals.integer)
8708 if (r_showdisabledepthtest.integer)
8710 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8711 GL_DepthMask(false);
8715 GL_BlendFunc(GL_ONE, GL_ZERO);
8718 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8720 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8722 rsurface.texture = R_GetCurrentTexture(surface->texture);
8723 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8725 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8726 if (r_showtris.value > 0)
8728 if (!rsurface.texture->currentlayers->depthmask)
8729 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8730 else if (ent == r_refdef.scene.worldentity)
8731 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8733 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8734 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8735 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8736 R_Mesh_ColorPointer(NULL, 0, 0);
8737 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8738 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8739 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8740 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);
8741 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8744 if (r_shownormals.value < 0)
8747 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8749 VectorCopy(rsurface.vertex3f + l * 3, v);
8750 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8751 qglVertex3f(v[0], v[1], v[2]);
8752 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8753 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8754 qglVertex3f(v[0], v[1], v[2]);
8759 if (r_shownormals.value > 0)
8762 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8764 VectorCopy(rsurface.vertex3f + l * 3, v);
8765 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8766 qglVertex3f(v[0], v[1], v[2]);
8767 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8768 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8769 qglVertex3f(v[0], v[1], v[2]);
8774 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8776 VectorCopy(rsurface.vertex3f + l * 3, v);
8777 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8778 qglVertex3f(v[0], v[1], v[2]);
8779 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8780 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8781 qglVertex3f(v[0], v[1], v[2]);
8786 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8788 VectorCopy(rsurface.vertex3f + l * 3, v);
8789 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8790 qglVertex3f(v[0], v[1], v[2]);
8791 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8792 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8793 qglVertex3f(v[0], v[1], v[2]);
8800 rsurface.texture = NULL;
8804 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8805 int r_maxsurfacelist = 0;
8806 const msurface_t **r_surfacelist = NULL;
8807 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8809 int i, j, endj, f, flagsmask;
8811 dp_model_t *model = r_refdef.scene.worldmodel;
8812 msurface_t *surfaces;
8813 unsigned char *update;
8814 int numsurfacelist = 0;
8818 if (r_maxsurfacelist < model->num_surfaces)
8820 r_maxsurfacelist = model->num_surfaces;
8822 Mem_Free(r_surfacelist);
8823 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8826 RSurf_ActiveWorldEntity();
8828 surfaces = model->data_surfaces;
8829 update = model->brushq1.lightmapupdateflags;
8831 // update light styles on this submodel
8832 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8834 model_brush_lightstyleinfo_t *style;
8835 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8837 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8839 int *list = style->surfacelist;
8840 style->value = r_refdef.scene.lightstylevalue[style->style];
8841 for (j = 0;j < style->numsurfaces;j++)
8842 update[list[j]] = true;
8847 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8852 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8858 rsurface.uselightmaptexture = false;
8859 rsurface.texture = NULL;
8860 rsurface.rtlight = NULL;
8862 // add visible surfaces to draw list
8863 for (i = 0;i < model->nummodelsurfaces;i++)
8865 j = model->sortedmodelsurfaces[i];
8866 if (r_refdef.viewcache.world_surfacevisible[j])
8867 r_surfacelist[numsurfacelist++] = surfaces + j;
8869 // update lightmaps if needed
8871 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8872 if (r_refdef.viewcache.world_surfacevisible[j])
8874 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8875 // don't do anything if there were no surfaces
8876 if (!numsurfacelist)
8878 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8881 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8882 GL_AlphaTest(false);
8884 // add to stats if desired
8885 if (r_speeds.integer && !skysurfaces && !depthonly)
8887 r_refdef.stats.world_surfaces += numsurfacelist;
8888 for (j = 0;j < numsurfacelist;j++)
8889 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8892 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8895 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8897 int i, j, endj, f, flagsmask;
8899 dp_model_t *model = ent->model;
8900 msurface_t *surfaces;
8901 unsigned char *update;
8902 int numsurfacelist = 0;
8906 if (r_maxsurfacelist < model->num_surfaces)
8908 r_maxsurfacelist = model->num_surfaces;
8910 Mem_Free(r_surfacelist);
8911 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8914 // if the model is static it doesn't matter what value we give for
8915 // wantnormals and wanttangents, so this logic uses only rules applicable
8916 // to a model, knowing that they are meaningless otherwise
8917 if (ent == r_refdef.scene.worldentity)
8918 RSurf_ActiveWorldEntity();
8919 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8920 RSurf_ActiveModelEntity(ent, false, false);
8922 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8924 surfaces = model->data_surfaces;
8925 update = model->brushq1.lightmapupdateflags;
8927 // update light styles
8928 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8930 model_brush_lightstyleinfo_t *style;
8931 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8933 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8935 int *list = style->surfacelist;
8936 style->value = r_refdef.scene.lightstylevalue[style->style];
8937 for (j = 0;j < style->numsurfaces;j++)
8938 update[list[j]] = true;
8943 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8948 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8954 rsurface.uselightmaptexture = false;
8955 rsurface.texture = NULL;
8956 rsurface.rtlight = NULL;
8958 // add visible surfaces to draw list
8959 for (i = 0;i < model->nummodelsurfaces;i++)
8960 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8961 // don't do anything if there were no surfaces
8962 if (!numsurfacelist)
8964 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8967 // update lightmaps if needed
8969 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8971 R_BuildLightMap(ent, surfaces + j);
8972 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8973 GL_AlphaTest(false);
8975 // add to stats if desired
8976 if (r_speeds.integer && !skysurfaces && !depthonly)
8978 r_refdef.stats.entities_surfaces += numsurfacelist;
8979 for (j = 0;j < numsurfacelist;j++)
8980 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8983 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8986 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
8988 static texture_t texture;
8989 static msurface_t surface;
8990 const msurface_t *surfacelist = &surface;
8992 // fake enough texture and surface state to render this geometry
8994 texture.update_lastrenderframe = -1; // regenerate this texture
8995 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
8996 texture.currentskinframe = skinframe;
8997 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
8998 texture.specularscalemod = 1;
8999 texture.specularpowermod = 1;
9001 surface.texture = &texture;
9002 surface.num_triangles = numtriangles;
9003 surface.num_firsttriangle = firsttriangle;
9004 surface.num_vertices = numvertices;
9005 surface.num_firstvertex = firstvertex;
9008 rsurface.texture = R_GetCurrentTexture(surface.texture);
9009 rsurface.uselightmaptexture = false;
9010 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);