2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
33 qboolean r_loadnormalmap;
42 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
43 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
44 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
45 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
46 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
47 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
48 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
49 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
51 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
52 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
53 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
54 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
55 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
57 cvar_t r_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"};
58 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
59 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
60 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
61 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
62 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
63 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)"};
64 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
65 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
66 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"};
67 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"};
68 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
69 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"};
70 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"};
71 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"};
72 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
73 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
74 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
75 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
76 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
77 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
78 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
79 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
80 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
81 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
82 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
83 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
84 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
85 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."};
86 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
87 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
88 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
89 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."};
90 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
91 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
92 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"};
93 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"};
94 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
95 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
96 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
97 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
98 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
100 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
101 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
102 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
103 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
104 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
105 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
106 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
107 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
109 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
110 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
111 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
113 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)"};
114 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
115 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
116 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
117 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
118 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)"};
119 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)"};
120 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)"};
121 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)"};
123 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)"};
124 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
125 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"};
126 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
127 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
129 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
130 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
131 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
132 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
134 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
135 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
136 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
137 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
138 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
139 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
140 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
142 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
143 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
144 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
145 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)"};
147 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"};
149 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"};
151 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
153 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
154 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
155 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"};
156 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
157 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
158 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
159 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
161 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
163 extern cvar_t v_glslgamma;
165 extern qboolean v_flipped_state;
167 static struct r_bloomstate_s
172 int bloomwidth, bloomheight;
174 int screentexturewidth, screentextureheight;
175 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
177 int bloomtexturewidth, bloomtextureheight;
178 rtexture_t *texture_bloom;
180 // arrays for rendering the screen passes
181 float screentexcoord2f[8];
182 float bloomtexcoord2f[8];
183 float offsettexcoord2f[8];
185 r_viewport_t viewport;
189 r_waterstate_t r_waterstate;
191 /// shadow volume bsp struct with automatically growing nodes buffer
194 rtexture_t *r_texture_blanknormalmap;
195 rtexture_t *r_texture_white;
196 rtexture_t *r_texture_grey128;
197 rtexture_t *r_texture_black;
198 rtexture_t *r_texture_notexture;
199 rtexture_t *r_texture_whitecube;
200 rtexture_t *r_texture_normalizationcube;
201 rtexture_t *r_texture_fogattenuation;
202 rtexture_t *r_texture_gammaramps;
203 unsigned int r_texture_gammaramps_serial;
204 //rtexture_t *r_texture_fogintensity;
206 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
207 unsigned int r_numqueries;
208 unsigned int r_maxqueries;
210 typedef struct r_qwskincache_s
212 char name[MAX_QPATH];
213 skinframe_t *skinframe;
217 static r_qwskincache_t *r_qwskincache;
218 static int r_qwskincache_size;
220 /// vertex coordinates for a quad that covers the screen exactly
221 const float r_screenvertex3f[12] =
229 extern void R_DrawModelShadows(void);
231 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
234 for (i = 0;i < verts;i++)
245 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
248 for (i = 0;i < verts;i++)
258 // FIXME: move this to client?
261 if (gamemode == GAME_NEHAHRA)
263 Cvar_Set("gl_fogenable", "0");
264 Cvar_Set("gl_fogdensity", "0.2");
265 Cvar_Set("gl_fogred", "0.3");
266 Cvar_Set("gl_foggreen", "0.3");
267 Cvar_Set("gl_fogblue", "0.3");
269 r_refdef.fog_density = 0;
270 r_refdef.fog_red = 0;
271 r_refdef.fog_green = 0;
272 r_refdef.fog_blue = 0;
273 r_refdef.fog_alpha = 1;
274 r_refdef.fog_start = 0;
275 r_refdef.fog_end = 16384;
276 r_refdef.fog_height = 1<<30;
277 r_refdef.fog_fadedepth = 128;
280 static void R_BuildBlankTextures(void)
282 unsigned char data[4];
283 data[2] = 128; // normal X
284 data[1] = 128; // normal Y
285 data[0] = 255; // normal Z
286 data[3] = 128; // height
287 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
292 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
297 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
302 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
305 static void R_BuildNoTexture(void)
308 unsigned char pix[16][16][4];
309 // this makes a light grey/dark grey checkerboard texture
310 for (y = 0;y < 16;y++)
312 for (x = 0;x < 16;x++)
314 if ((y < 8) ^ (x < 8))
330 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
333 static void R_BuildWhiteCube(void)
335 unsigned char data[6*1*1*4];
336 memset(data, 255, sizeof(data));
337 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
340 static void R_BuildNormalizationCube(void)
344 vec_t s, t, intensity;
347 data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
348 for (side = 0;side < 6;side++)
350 for (y = 0;y < NORMSIZE;y++)
352 for (x = 0;x < NORMSIZE;x++)
354 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
355 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
390 intensity = 127.0f / sqrt(DotProduct(v, v));
391 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
392 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
393 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
394 data[((side*64+y)*64+x)*4+3] = 255;
398 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
402 static void R_BuildFogTexture(void)
406 unsigned char data1[FOGWIDTH][4];
407 //unsigned char data2[FOGWIDTH][4];
410 r_refdef.fogmasktable_start = r_refdef.fog_start;
411 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
412 r_refdef.fogmasktable_range = r_refdef.fogrange;
413 r_refdef.fogmasktable_density = r_refdef.fog_density;
415 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
416 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
418 d = (x * r - r_refdef.fogmasktable_start);
419 if(developer.integer >= 100)
420 Con_Printf("%f ", d);
422 if (r_fog_exp2.integer)
423 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
425 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
426 if(developer.integer >= 100)
427 Con_Printf(" : %f ", alpha);
428 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
429 if(developer.integer >= 100)
430 Con_Printf(" = %f\n", alpha);
431 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
434 for (x = 0;x < FOGWIDTH;x++)
436 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
441 //data2[x][0] = 255 - b;
442 //data2[x][1] = 255 - b;
443 //data2[x][2] = 255 - b;
446 if (r_texture_fogattenuation)
448 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
449 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
453 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
454 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
458 static const char *builtinshaderstring =
459 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
460 "// written by Forest 'LordHavoc' Hale\n"
462 "// enable various extensions depending on permutation:\n"
464 "#ifdef MODE_DEPTH_OR_SHADOW\n"
465 "#ifdef VERTEX_SHADER\n"
468 " gl_Position = ftransform();\n"
471 "#else // !MODE_DEPTH_ORSHADOW\n"
472 "#ifdef MODE_SHOWDEPTH\n"
473 "#ifdef VERTEX_SHADER\n"
476 " gl_Position = ftransform();\n"
477 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
481 "#ifdef FRAGMENT_SHADER\n"
484 " gl_FragColor = gl_Color;\n"
487 "#else // !MODE_SHOWDEPTH\n"
488 "#ifdef MODE_POSTPROCESS\n"
489 "varying vec2 TexCoord1;\n"
490 "varying vec2 TexCoord2;\n"
492 "#ifdef VERTEX_SHADER\n"
495 " gl_Position = ftransform();\n"
496 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
498 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
503 "#ifdef FRAGMENT_SHADER\n"
504 "uniform sampler2D Texture_First;\n"
506 "uniform sampler2D Texture_Second;\n"
508 "#ifdef USEGAMMARAMPS\n"
509 "uniform sampler2D Texture_GammaRamps;\n"
511 "#ifdef USESATURATION\n"
512 "uniform float Saturation;\n"
514 "#ifdef USEVIEWTINT\n"
515 "uniform vec4 ViewTintColor;\n"
517 "//uncomment these if you want to use them:\n"
518 "uniform vec4 UserVec1;\n"
519 "// uniform vec4 UserVec2;\n"
520 "// uniform vec4 UserVec3;\n"
521 "// uniform vec4 UserVec4;\n"
522 "// uniform float ClientTime;\n"
523 "uniform vec2 PixelSize;\n"
526 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
528 " gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
530 "#ifdef USEVIEWTINT\n"
531 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
534 "#ifdef USEPOSTPROCESSING\n"
535 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
536 "// 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"
537 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
538 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
539 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
540 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
541 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
542 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
545 "#ifdef USESATURATION\n"
546 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
547 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
548 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
549 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
552 "#ifdef USEGAMMARAMPS\n"
553 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
554 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
555 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
559 "#else // !MODE_POSTPROCESS\n"
560 "#ifdef MODE_GENERIC\n"
561 "#ifdef USEDIFFUSE\n"
562 "varying vec2 TexCoord1;\n"
564 "#ifdef USESPECULAR\n"
565 "varying vec2 TexCoord2;\n"
567 "#ifdef VERTEX_SHADER\n"
570 " gl_FrontColor = gl_Color;\n"
571 "#ifdef USEDIFFUSE\n"
572 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
574 "#ifdef USESPECULAR\n"
575 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
577 " gl_Position = ftransform();\n"
581 "#ifdef FRAGMENT_SHADER\n"
582 "#ifdef USEDIFFUSE\n"
583 "uniform sampler2D Texture_First;\n"
585 "#ifdef USESPECULAR\n"
586 "uniform sampler2D Texture_Second;\n"
591 " gl_FragColor = gl_Color;\n"
592 "#ifdef USEDIFFUSE\n"
593 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
596 "#ifdef USESPECULAR\n"
597 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
599 "#ifdef USECOLORMAPPING\n"
600 " gl_FragColor *= tex2;\n"
603 " gl_FragColor += tex2;\n"
605 "#ifdef USEVERTEXTEXTUREBLEND\n"
606 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
610 "#else // !MODE_GENERIC\n"
611 "#ifdef MODE_BLOOMBLUR\n"
612 "varying TexCoord;\n"
613 "#ifdef VERTEX_SHADER\n"
616 " gl_FrontColor = gl_Color;\n"
617 " TexCoord = gl_MultiTexCoord0.xy;\n"
618 " gl_Position = ftransform();\n"
622 "#ifdef FRAGMENT_SHADER\n"
623 "uniform sampler2D Texture_First;\n"
624 "uniform vec4 BloomBlur_Parameters;\n"
629 " vec2 tc = TexCoord;\n"
630 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
631 " tc += BloomBlur_Parameters.xy;\n"
632 " for (i = 1;i < SAMPLES;i++)\n"
634 " color += texture2D(Texture_First, tc).rgb;\n"
635 " tc += BloomBlur_Parameters.xy;\n"
637 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
640 "#else // !MODE_BLOOMBLUR\n"
641 "#ifdef MODE_REFRACTION\n"
642 "varying vec2 TexCoord;\n"
643 "varying vec4 ModelViewProjectionPosition;\n"
644 "uniform mat4 TexMatrix;\n"
645 "#ifdef VERTEX_SHADER\n"
649 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
650 " gl_Position = ftransform();\n"
651 " ModelViewProjectionPosition = gl_Position;\n"
655 "#ifdef FRAGMENT_SHADER\n"
656 "uniform sampler2D Texture_Normal;\n"
657 "uniform sampler2D Texture_Refraction;\n"
658 "uniform sampler2D Texture_Reflection;\n"
660 "uniform vec4 DistortScaleRefractReflect;\n"
661 "uniform vec4 ScreenScaleRefractReflect;\n"
662 "uniform vec4 ScreenCenterRefractReflect;\n"
663 "uniform vec4 RefractColor;\n"
664 "uniform vec4 ReflectColor;\n"
665 "uniform float ReflectFactor;\n"
666 "uniform float ReflectOffset;\n"
670 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
671 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
672 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
673 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
674 " // FIXME temporary hack to detect the case that the reflection\n"
675 " // gets blackened at edges due to leaving the area that contains actual\n"
677 " // Remove this 'ack once we have a better way to stop this thing from\n"
679 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
680 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
681 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
682 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
683 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
684 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
687 "#else // !MODE_REFRACTION\n"
688 "#ifdef MODE_WATER\n"
689 "varying vec2 TexCoord;\n"
690 "varying vec3 EyeVector;\n"
691 "varying vec4 ModelViewProjectionPosition;\n"
692 "#ifdef VERTEX_SHADER\n"
693 "uniform vec3 EyePosition;\n"
694 "uniform mat4 TexMatrix;\n"
698 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
699 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
700 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
701 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
702 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
703 " gl_Position = ftransform();\n"
704 " ModelViewProjectionPosition = gl_Position;\n"
708 "#ifdef FRAGMENT_SHADER\n"
709 "uniform sampler2D Texture_Normal;\n"
710 "uniform sampler2D Texture_Refraction;\n"
711 "uniform sampler2D Texture_Reflection;\n"
713 "uniform vec4 DistortScaleRefractReflect;\n"
714 "uniform vec4 ScreenScaleRefractReflect;\n"
715 "uniform vec4 ScreenCenterRefractReflect;\n"
716 "uniform vec4 RefractColor;\n"
717 "uniform vec4 ReflectColor;\n"
718 "uniform float ReflectFactor;\n"
719 "uniform float ReflectOffset;\n"
723 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
724 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
725 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
726 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
727 " // FIXME temporary hack to detect the case that the reflection\n"
728 " // gets blackened at edges due to leaving the area that contains actual\n"
730 " // Remove this 'ack once we have a better way to stop this thing from\n"
732 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
733 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
734 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
735 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
736 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
737 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
738 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
739 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
740 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
741 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
742 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
743 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
746 "#else // !MODE_WATER\n"
748 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
749 "# extension GL_ARB_texture_rectangle : enable\n"
752 "#ifdef USESHADOWMAP2D\n"
753 "# ifdef GL_EXT_gpu_shader4\n"
754 "# extension GL_EXT_gpu_shader4 : enable\n"
756 "# ifdef GL_ARB_texture_gather\n"
757 "# extension GL_ARB_texture_gather : enable\n"
759 "# ifdef GL_AMD_texture_texture4\n"
760 "# extension GL_AMD_texture_texture4 : enable\n"
765 "#ifdef USESHADOWMAPCUBE\n"
766 "# extension GL_EXT_gpu_shader4 : enable\n"
769 "#ifdef USESHADOWSAMPLER\n"
770 "# extension GL_ARB_shadow : enable\n"
773 "// common definitions between vertex shader and fragment shader:\n"
775 "//#ifdef __GLSL_CG_DATA_TYPES\n"
776 "//# define myhalf half\n"
777 "//# define myhalf2 half2\n"
778 "//# define myhalf3half3\n"
779 "//# define myhalf4 half4\n"
781 "# define myhalf float\n"
782 "# define myhalf2 vec2\n"
783 "# define myhalf3 vec3\n"
784 "# define myhalf4 vec4\n"
787 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
791 "varying vec2 TexCoord;\n"
792 "#ifdef USEVERTEXTEXTUREBLEND\n"
793 "varying vec2 TexCoord2;\n"
795 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
796 "#define USELIGHTMAP\n"
797 "varying vec2 TexCoordLightmap;\n"
800 "#ifdef MODE_LIGHTSOURCE\n"
801 "varying vec3 CubeVector;\n"
804 "#ifdef MODE_LIGHTSOURCE\n"
805 "varying vec3 LightVector;\n"
807 "#if defined(MODE_LIGHTDIRECTION)\n"
808 "varying vec3 LightVector;\n"
811 "#if defined(USEOFFSETMAPPING) || defined(USESPECULAR)\n"
812 "//#if defined(USEOFFSETMAPPING) || defined(USESPECULAR) || defined(MODE_LIGHTDIRECTION) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
813 "#define USEEYEVECTOR\n"
814 "varying vec3 EyeVector;\n"
817 "varying vec3 EyeVectorModelSpace;\n"
818 "varying float FogPlaneVertexDist;\n"
821 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
822 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
823 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
824 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
827 "#ifdef USEREFLECTION\n"
828 "varying vec4 ModelViewProjectionPosition;\n"
830 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
831 "uniform vec3 LightPosition;\n"
832 "varying vec4 ModelViewPosition;\n"
835 "#ifdef MODE_LIGHTSOURCE\n"
836 "uniform vec3 LightPosition;\n"
838 "uniform vec3 EyePosition;\n"
839 "#ifdef MODE_LIGHTDIRECTION\n"
840 "uniform vec3 LightDir;\n"
842 "uniform vec4 FogPlane;\n"
848 "// vertex shader specific:\n"
849 "#ifdef VERTEX_SHADER\n"
851 "// 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"
853 "#ifdef MODE_DEFERREDGEOMETRY\n"
854 "uniform mat4 TexMatrix;\n"
855 "#ifdef USEVERTEXTEXTUREBLEND\n"
856 "uniform mat4 BackgroundTexMatrix;\n"
860 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
861 "#ifdef USEVERTEXTEXTUREBLEND\n"
862 " gl_FrontColor = gl_Color;\n"
863 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
866 " // transform unnormalized eye direction into tangent space\n"
867 "#ifdef USEOFFSETMAPPING\n"
868 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
869 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
870 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
871 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
874 " VectorS = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz).xyz;\n"
875 " VectorT = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz).xyz;\n"
876 " VectorR = normalize(gl_NormalMatrix * gl_MultiTexCoord3.xyz).xyz;\n"
877 " gl_Position = ftransform();\n"
879 "#else // !MODE_DEFERREDGEOMETRY\n"
880 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
883 " ModelViewPosition = gl_ModelViewMatrix * gl_Vertex;\n"
884 " gl_Position = ftransform();\n"
886 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
887 "uniform mat4 TexMatrix;\n"
888 "#ifdef USEVERTEXTEXTUREBLEND\n"
889 "uniform mat4 BackgroundTexMatrix;\n"
891 "#ifdef MODE_LIGHTSOURCE\n"
892 "uniform mat4 ModelToLight;\n"
896 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
897 " gl_FrontColor = gl_Color;\n"
899 " // copy the surface texcoord\n"
900 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
901 "#ifdef USEVERTEXTEXTUREBLEND\n"
902 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
904 "#ifdef USELIGHTMAP\n"
905 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
908 "#ifdef MODE_LIGHTSOURCE\n"
909 " // transform vertex position into light attenuation/cubemap space\n"
910 " // (-1 to +1 across the light box)\n"
911 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
913 "# ifdef USEDIFFUSE\n"
914 " // transform unnormalized light direction into tangent space\n"
915 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
916 " // normalize it per pixel)\n"
917 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
918 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
919 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
920 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
924 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
925 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
926 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
927 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
930 " // transform unnormalized eye direction into tangent space\n"
931 "#ifdef USEEYEVECTOR\n"
933 " vec3 EyeVectorModelSpace;\n"
935 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
936 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
937 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
938 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
942 "#ifndef USEEYEVECTOR\n"
943 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
945 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
948 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
949 " VectorS = gl_MultiTexCoord1.xyz;\n"
950 " VectorT = gl_MultiTexCoord2.xyz;\n"
951 " VectorR = gl_MultiTexCoord3.xyz;\n"
954 "//#if defined(USEREFLECTION)\n"
955 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
956 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
957 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
960 "// transform vertex to camera space, using ftransform to match non-VS\n"
962 " gl_Position = ftransform();\n"
964 "#ifdef USEREFLECTION\n"
965 " ModelViewProjectionPosition = gl_Position;\n"
968 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
969 "#endif // !MODE_DEFERREDGEOMETRY\n"
971 "#endif // VERTEX_SHADER\n"
976 "// fragment shader specific:\n"
977 "#ifdef FRAGMENT_SHADER\n"
979 "uniform sampler2D Texture_Normal;\n"
980 "uniform sampler2D Texture_Color;\n"
981 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
982 "uniform sampler2D Texture_Gloss;\n"
985 "uniform sampler2D Texture_Glow;\n"
987 "#ifdef USEVERTEXTEXTUREBLEND\n"
988 "uniform sampler2D Texture_SecondaryNormal;\n"
989 "uniform sampler2D Texture_SecondaryColor;\n"
990 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
991 "uniform sampler2D Texture_SecondaryGloss;\n"
994 "uniform sampler2D Texture_SecondaryGlow;\n"
997 "#ifdef USECOLORMAPPING\n"
998 "uniform sampler2D Texture_Pants;\n"
999 "uniform sampler2D Texture_Shirt;\n"
1002 "uniform sampler2D Texture_FogMask;\n"
1004 "#ifdef USELIGHTMAP\n"
1005 "uniform sampler2D Texture_Lightmap;\n"
1007 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1008 "uniform sampler2D Texture_Deluxemap;\n"
1010 "#ifdef USEREFLECTION\n"
1011 "uniform sampler2D Texture_Reflection;\n"
1014 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1015 "uniform sampler2DRect Texture_ScreenDepth;\n"
1016 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
1018 "#ifdef USEDEFERREDLIGHTMAP\n"
1019 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
1020 "uniform sampler2DRect Texture_ScreenSpecular;\n"
1023 "uniform myhalf3 Color_Pants;\n"
1024 "uniform myhalf3 Color_Shirt;\n"
1025 "uniform myhalf3 FogColor;\n"
1028 "uniform float FogRangeRecip;\n"
1029 "uniform float FogPlaneViewDist;\n"
1030 "uniform float FogHeightFade;\n"
1031 "myhalf FogVertex(void)\n"
1034 "#ifdef USEFOGOUTSIDE\n"
1035 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1037 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1039 " return myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1043 "#ifdef USEOFFSETMAPPING\n"
1044 "uniform float OffsetMapping_Scale;\n"
1045 "vec2 OffsetMapping(vec2 TexCoord)\n"
1047 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1048 " // 14 sample relief mapping: linear search and then binary search\n"
1049 " // this basically steps forward a small amount repeatedly until it finds\n"
1050 " // itself inside solid, then jitters forward and back using decreasing\n"
1051 " // amounts to find the impact\n"
1052 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1053 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1054 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1055 " vec3 RT = vec3(TexCoord, 1);\n"
1056 " OffsetVector *= 0.1;\n"
1057 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1058 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1059 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1060 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1061 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1062 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1063 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1064 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1065 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1066 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1067 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1068 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1069 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1070 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1073 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1074 " // this basically moves forward the full distance, and then backs up based\n"
1075 " // on height of samples\n"
1076 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1077 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1078 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1079 " TexCoord += OffsetVector;\n"
1080 " OffsetVector *= 0.333;\n"
1081 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1082 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1083 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1084 " return TexCoord;\n"
1087 "#endif // USEOFFSETMAPPING\n"
1089 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1090 "uniform sampler2D Texture_Attenuation;\n"
1091 "uniform samplerCube Texture_Cube;\n"
1093 "#ifdef USESHADOWMAPRECT\n"
1094 "# ifdef USESHADOWSAMPLER\n"
1095 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1097 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1101 "#ifdef USESHADOWMAP2D\n"
1102 "# ifdef USESHADOWSAMPLER\n"
1103 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1105 "uniform sampler2D Texture_ShadowMap2D;\n"
1109 "#ifdef USESHADOWMAPVSDCT\n"
1110 "uniform samplerCube Texture_CubeProjection;\n"
1113 "#ifdef USESHADOWMAPCUBE\n"
1114 "# ifdef USESHADOWSAMPLER\n"
1115 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1117 "uniform samplerCube Texture_ShadowMapCube;\n"
1121 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1122 "uniform vec2 ShadowMap_TextureScale;\n"
1123 "uniform vec4 ShadowMap_Parameters;\n"
1126 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1127 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1129 " vec3 adir = abs(dir);\n"
1130 "# ifndef USESHADOWMAPVSDCT\n"
1134 " if (adir.x > adir.y)\n"
1136 " if (adir.x > adir.z) // X\n"
1140 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1146 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1151 " if (adir.y > adir.z) // Y\n"
1155 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1161 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1165 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1166 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1167 " stc.z += ShadowMap_Parameters.z;\n"
1170 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1171 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1172 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1173 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1174 " stc.z += ShadowMap_Parameters.z;\n"
1178 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1180 "#ifdef USESHADOWMAPCUBE\n"
1181 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1183 " vec3 adir = abs(dir);\n"
1184 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1188 "# ifdef USESHADOWMAPRECT\n"
1189 "float ShadowMapCompare(vec3 dir)\n"
1191 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1193 "# ifdef USESHADOWSAMPLER\n"
1195 "# ifdef USESHADOWMAPPCF\n"
1196 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1197 " 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"
1199 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1204 "# ifdef USESHADOWMAPPCF\n"
1205 "# if USESHADOWMAPPCF > 1\n"
1206 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1207 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1208 " 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"
1209 " 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"
1210 " 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"
1211 " 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"
1212 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1213 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1215 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1216 " vec2 offset = fract(shadowmaptc.xy);\n"
1217 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1218 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1219 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1220 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1221 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1224 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1232 "# ifdef USESHADOWMAP2D\n"
1233 "float ShadowMapCompare(vec3 dir)\n"
1235 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1238 "# ifdef USESHADOWSAMPLER\n"
1239 "# ifdef USESHADOWMAPPCF\n"
1240 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1241 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1242 " 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"
1244 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1247 "# ifdef USESHADOWMAPPCF\n"
1248 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1249 "# ifdef GL_ARB_texture_gather\n"
1250 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1252 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1254 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1255 " center *= ShadowMap_TextureScale;\n"
1256 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1257 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1258 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1259 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1260 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1261 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1262 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1264 "# ifdef GL_EXT_gpu_shader4\n"
1265 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1267 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1269 "# if USESHADOWMAPPCF > 1\n"
1270 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1271 " center *= ShadowMap_TextureScale;\n"
1272 " 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"
1273 " 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"
1274 " 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"
1275 " 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"
1276 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1277 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1279 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1280 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1281 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1282 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1283 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1284 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1288 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1295 "# ifdef USESHADOWMAPCUBE\n"
1296 "float ShadowMapCompare(vec3 dir)\n"
1298 " // apply depth texture cubemap as light filter\n"
1299 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1301 "# ifdef USESHADOWSAMPLER\n"
1302 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1304 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1309 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1311 "#ifdef MODE_DEFERREDGEOMETRY\n"
1314 "#ifdef USEOFFSETMAPPING\n"
1315 " // apply offsetmapping\n"
1316 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1317 "#define TexCoord TexCoordOffset\n"
1320 "#ifdef USEALPHAKILL\n"
1321 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1325 "#ifdef USEVERTEXTEXTUREBLEND\n"
1326 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1327 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1328 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1329 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1332 "#ifdef USEVERTEXTEXTUREBLEND\n"
1333 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1335 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1338 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1340 "#else // !MODE_DEFERREDGEOMETRY\n"
1341 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1342 "uniform mat4 ViewToLight;\n"
1343 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1344 "uniform vec2 ScreenToDepth;\n"
1345 "uniform myhalf3 DeferredColor_Ambient;\n"
1346 "uniform myhalf3 DeferredColor_Diffuse;\n"
1347 "#ifdef USESPECULAR\n"
1348 "uniform myhalf3 DeferredColor_Specular;\n"
1349 "uniform myhalf SpecularPower;\n"
1353 " // calculate viewspace pixel position\n"
1355 " position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1356 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1357 " // decode viewspace pixel normal\n"
1358 " myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1359 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1360 " // surfacenormal = pixel normal in viewspace\n"
1361 " // LightVector = pixel to light in viewspace\n"
1362 " // CubeVector = position in lightspace\n"
1363 " // eyevector = pixel to view in viewspace\n"
1364 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1365 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1366 "#ifdef USEDIFFUSE\n"
1367 " // calculate diffuse shading\n"
1368 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1369 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1371 "#ifdef USESPECULAR\n"
1372 " // calculate directional shading\n"
1373 " vec3 eyevector = position * -1.0;\n"
1374 "# ifdef USEEXACTSPECULARMATH\n"
1375 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1377 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1378 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1382 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1383 " fade *= ShadowMapCompare(CubeVector);\n"
1386 "#ifdef USEDIFFUSE\n"
1387 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1389 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1391 "#ifdef USESPECULAR\n"
1392 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1394 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1397 "# ifdef USECUBEFILTER\n"
1398 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1399 " gl_FragData[0] *= cubecolor;\n"
1400 " gl_FragData[1] *= cubecolor;\n"
1403 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1404 "#ifdef USEDEFERREDLIGHTMAP\n"
1405 "uniform myhalf3 DeferredMod_Diffuse;\n"
1406 "uniform myhalf3 DeferredMod_Specular;\n"
1408 "uniform myhalf3 Color_Ambient;\n"
1409 "uniform myhalf3 Color_Diffuse;\n"
1410 "uniform myhalf3 Color_Specular;\n"
1411 "uniform myhalf SpecularPower;\n"
1413 "uniform myhalf3 Color_Glow;\n"
1415 "uniform myhalf Alpha;\n"
1416 "#ifdef USEREFLECTION\n"
1417 "uniform vec4 DistortScaleRefractReflect;\n"
1418 "uniform vec4 ScreenScaleRefractReflect;\n"
1419 "uniform vec4 ScreenCenterRefractReflect;\n"
1420 "uniform myhalf4 ReflectColor;\n"
1422 "#ifdef MODE_LIGHTDIRECTION\n"
1423 "uniform myhalf3 LightColor;\n"
1425 "#ifdef MODE_LIGHTSOURCE\n"
1426 "uniform myhalf3 LightColor;\n"
1430 "#ifdef USEOFFSETMAPPING\n"
1431 " // apply offsetmapping\n"
1432 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1433 "#define TexCoord TexCoordOffset\n"
1436 " // combine the diffuse textures (base, pants, shirt)\n"
1437 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1438 "#ifdef USEALPHAKILL\n"
1439 " if (color.a < 0.5)\n"
1442 " color.a *= Alpha;\n"
1443 "#ifdef USECOLORMAPPING\n"
1444 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1446 "#ifdef USEVERTEXTEXTUREBLEND\n"
1447 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1448 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1449 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1450 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1452 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1455 " // get the surface normal\n"
1456 "#ifdef USEVERTEXTEXTUREBLEND\n"
1457 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1459 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1462 " // get the material colors\n"
1463 " myhalf3 diffusetex = color.rgb;\n"
1464 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1465 "# ifdef USEVERTEXTEXTUREBLEND\n"
1466 " myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1468 " myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1475 "#ifdef MODE_LIGHTSOURCE\n"
1476 " // light source\n"
1477 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1478 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1479 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1480 "#ifdef USESPECULAR\n"
1481 "#ifdef USEEXACTSPECULARMATH\n"
1482 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1484 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1485 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1487 " color.rgb += glosstex * (specular * Color_Specular);\n"
1489 " color.rgb *= LightColor;\n"
1490 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1491 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1492 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1494 "# ifdef USECUBEFILTER\n"
1495 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1497 "#endif // MODE_LIGHTSOURCE\n"
1502 "#ifdef MODE_LIGHTDIRECTION\n"
1504 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1505 "#define lightcolor LightColor\n"
1506 "#endif // MODE_LIGHTDIRECTION\n"
1507 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1509 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1510 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1511 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1512 " // convert modelspace light vector to tangentspace\n"
1513 " myhalf3 lightnormal;\n"
1514 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1515 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1516 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1517 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1518 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1519 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1520 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1521 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1522 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1523 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1524 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1525 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1526 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1527 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1528 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1530 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1531 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1532 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1538 "#ifdef MODE_LIGHTMAP\n"
1539 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1540 "#endif // MODE_LIGHTMAP\n"
1541 "#ifdef MODE_VERTEXCOLOR\n"
1542 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1543 "#endif // MODE_VERTEXCOLOR\n"
1544 "#ifdef MODE_FLATCOLOR\n"
1545 " color.rgb = diffusetex * Color_Ambient;\n"
1546 "#endif // MODE_FLATCOLOR\n"
1552 "# ifdef USEDIFFUSE\n"
1553 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1554 "# ifdef USESPECULAR\n"
1555 "# ifdef USEEXACTSPECULARMATH\n"
1556 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1558 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1559 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1561 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1563 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1566 " color.rgb = diffusetex * Color_Ambient;\n"
1570 "#ifdef USEDEFERREDLIGHTMAP\n"
1571 " color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1572 " color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1576 "#ifdef USEVERTEXTEXTUREBLEND\n"
1577 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1579 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1584 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1587 " // 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"
1588 "#ifdef USEREFLECTION\n"
1589 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1590 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1591 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1592 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1593 " // FIXME temporary hack to detect the case that the reflection\n"
1594 " // gets blackened at edges due to leaving the area that contains actual\n"
1596 " // Remove this 'ack once we have a better way to stop this thing from\n"
1598 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1599 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1600 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1601 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1602 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1603 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1606 " gl_FragColor = vec4(color);\n"
1608 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1609 "#endif // !MODE_DEFERREDGEOMETRY\n"
1611 "#endif // FRAGMENT_SHADER\n"
1613 "#endif // !MODE_WATER\n"
1614 "#endif // !MODE_REFRACTION\n"
1615 "#endif // !MODE_BLOOMBLUR\n"
1616 "#endif // !MODE_GENERIC\n"
1617 "#endif // !MODE_POSTPROCESS\n"
1618 "#endif // !MODE_SHOWDEPTH\n"
1619 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1622 typedef struct shaderpermutationinfo_s
1624 const char *pretext;
1627 shaderpermutationinfo_t;
1629 typedef struct shadermodeinfo_s
1631 const char *vertexfilename;
1632 const char *geometryfilename;
1633 const char *fragmentfilename;
1634 const char *pretext;
1639 typedef enum shaderpermutation_e
1641 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1642 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1643 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1644 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1645 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1646 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1647 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1648 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1649 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1650 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1651 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1652 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1653 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1654 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1655 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1656 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1657 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1658 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1659 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1660 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1661 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1662 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1663 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1664 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1665 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
1666 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
1667 SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
1668 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
1670 shaderpermutation_t;
1672 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1673 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1675 {"#define USEDIFFUSE\n", " diffuse"},
1676 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1677 {"#define USEVIEWTINT\n", " viewtint"},
1678 {"#define USECOLORMAPPING\n", " colormapping"},
1679 {"#define USESATURATION\n", " saturation"},
1680 {"#define USEFOGINSIDE\n", " foginside"},
1681 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1682 {"#define USEGAMMARAMPS\n", " gammaramps"},
1683 {"#define USECUBEFILTER\n", " cubefilter"},
1684 {"#define USEGLOW\n", " glow"},
1685 {"#define USEBLOOM\n", " bloom"},
1686 {"#define USESPECULAR\n", " specular"},
1687 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1688 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1689 {"#define USEREFLECTION\n", " reflection"},
1690 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1691 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1692 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1693 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1694 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1695 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1696 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1697 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1698 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1699 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
1700 {"#define USEALPHAKILL\n", " alphakill"},
1703 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1704 typedef enum shadermode_e
1706 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1707 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1708 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1709 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1710 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1711 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1712 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1713 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1714 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1715 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1716 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1717 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1718 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1719 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
1720 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
1725 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1726 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1728 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1729 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1730 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1731 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1732 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1733 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1734 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1735 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1736 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1737 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1738 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1739 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1740 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1741 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1742 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1745 struct r_glsl_permutation_s;
1746 typedef struct r_glsl_permutation_s
1748 /// hash lookup data
1749 struct r_glsl_permutation_s *hashnext;
1751 unsigned int permutation;
1753 /// indicates if we have tried compiling this permutation already
1755 /// 0 if compilation failed
1757 /// locations of detected uniforms in program object, or -1 if not found
1758 int loc_Texture_First;
1759 int loc_Texture_Second;
1760 int loc_Texture_GammaRamps;
1761 int loc_Texture_Normal;
1762 int loc_Texture_Color;
1763 int loc_Texture_Gloss;
1764 int loc_Texture_Glow;
1765 int loc_Texture_SecondaryNormal;
1766 int loc_Texture_SecondaryColor;
1767 int loc_Texture_SecondaryGloss;
1768 int loc_Texture_SecondaryGlow;
1769 int loc_Texture_Pants;
1770 int loc_Texture_Shirt;
1771 int loc_Texture_FogMask;
1772 int loc_Texture_Lightmap;
1773 int loc_Texture_Deluxemap;
1774 int loc_Texture_Attenuation;
1775 int loc_Texture_Cube;
1776 int loc_Texture_Refraction;
1777 int loc_Texture_Reflection;
1778 int loc_Texture_ShadowMapRect;
1779 int loc_Texture_ShadowMapCube;
1780 int loc_Texture_ShadowMap2D;
1781 int loc_Texture_CubeProjection;
1782 int loc_Texture_ScreenDepth;
1783 int loc_Texture_ScreenNormalMap;
1784 int loc_Texture_ScreenDiffuse;
1785 int loc_Texture_ScreenSpecular;
1787 int loc_BloomBlur_Parameters;
1789 int loc_Color_Ambient;
1790 int loc_Color_Diffuse;
1791 int loc_Color_Specular;
1793 int loc_Color_Pants;
1794 int loc_Color_Shirt;
1795 int loc_DeferredColor_Ambient;
1796 int loc_DeferredColor_Diffuse;
1797 int loc_DeferredColor_Specular;
1798 int loc_DeferredMod_Diffuse;
1799 int loc_DeferredMod_Specular;
1800 int loc_DistortScaleRefractReflect;
1801 int loc_EyePosition;
1803 int loc_FogHeightFade;
1805 int loc_FogPlaneViewDist;
1806 int loc_FogRangeRecip;
1809 int loc_LightPosition;
1810 int loc_OffsetMapping_Scale;
1812 int loc_ReflectColor;
1813 int loc_ReflectFactor;
1814 int loc_ReflectOffset;
1815 int loc_RefractColor;
1817 int loc_ScreenCenterRefractReflect;
1818 int loc_ScreenScaleRefractReflect;
1819 int loc_ScreenToDepth;
1820 int loc_ShadowMap_Parameters;
1821 int loc_ShadowMap_TextureScale;
1822 int loc_SpecularPower;
1827 int loc_ViewTintColor;
1828 int loc_ViewToLight;
1829 int loc_ModelToLight;
1831 int loc_BackgroundTexMatrix;
1833 r_glsl_permutation_t;
1835 #define SHADERPERMUTATION_HASHSIZE 256
1837 /// information about each possible shader permutation
1838 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1839 /// currently selected permutation
1840 r_glsl_permutation_t *r_glsl_permutation;
1841 /// storage for permutations linked in the hash table
1842 memexpandablearray_t r_glsl_permutationarray;
1844 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1846 //unsigned int hashdepth = 0;
1847 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1848 r_glsl_permutation_t *p;
1849 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1851 if (p->mode == mode && p->permutation == permutation)
1853 //if (hashdepth > 10)
1854 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1859 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1861 p->permutation = permutation;
1862 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1863 r_glsl_permutationhash[mode][hashindex] = p;
1864 //if (hashdepth > 10)
1865 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1869 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1872 if (!filename || !filename[0])
1874 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1877 if (printfromdisknotice)
1878 Con_DPrintf("from disk %s... ", filename);
1879 return shaderstring;
1881 else if (!strcmp(filename, "glsl/default.glsl"))
1883 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1884 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1886 return shaderstring;
1889 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1892 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1893 int vertstrings_count = 0;
1894 int geomstrings_count = 0;
1895 int fragstrings_count = 0;
1896 char *vertexstring, *geometrystring, *fragmentstring;
1897 const char *vertstrings_list[32+3];
1898 const char *geomstrings_list[32+3];
1899 const char *fragstrings_list[32+3];
1900 char permutationname[256];
1907 permutationname[0] = 0;
1908 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1909 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1910 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1912 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1914 // the first pretext is which type of shader to compile as
1915 // (later these will all be bound together as a program object)
1916 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1917 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1918 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1920 // the second pretext is the mode (for example a light source)
1921 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1922 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1923 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1924 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1926 // now add all the permutation pretexts
1927 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1929 if (permutation & (1<<i))
1931 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1932 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1933 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1934 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1938 // keep line numbers correct
1939 vertstrings_list[vertstrings_count++] = "\n";
1940 geomstrings_list[geomstrings_count++] = "\n";
1941 fragstrings_list[fragstrings_count++] = "\n";
1945 // now append the shader text itself
1946 vertstrings_list[vertstrings_count++] = vertexstring;
1947 geomstrings_list[geomstrings_count++] = geometrystring;
1948 fragstrings_list[fragstrings_count++] = fragmentstring;
1950 // if any sources were NULL, clear the respective list
1952 vertstrings_count = 0;
1953 if (!geometrystring)
1954 geomstrings_count = 0;
1955 if (!fragmentstring)
1956 fragstrings_count = 0;
1958 // compile the shader program
1959 if (vertstrings_count + geomstrings_count + fragstrings_count)
1960 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1964 qglUseProgramObjectARB(p->program);CHECKGLERROR
1965 // look up all the uniform variable names we care about, so we don't
1966 // have to look them up every time we set them
1968 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1969 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1970 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1971 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1972 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1973 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1974 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1975 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1976 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1977 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1978 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1979 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1980 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1981 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1982 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1983 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1984 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1985 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1986 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1987 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1988 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1989 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1990 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1991 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1992 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
1993 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
1994 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
1995 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
1996 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
1997 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
1998 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1999 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
2000 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
2001 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
2002 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
2003 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
2004 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
2005 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
2006 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
2007 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
2008 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
2009 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
2010 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
2011 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
2012 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
2013 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
2014 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
2015 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
2016 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
2017 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
2018 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
2019 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
2020 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
2021 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
2022 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
2023 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
2024 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
2025 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
2026 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
2027 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
2028 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
2029 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
2030 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
2031 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
2032 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
2033 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
2034 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
2035 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
2036 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
2037 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
2038 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
2039 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
2040 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
2041 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
2042 // initialize the samplers to refer to the texture units we use
2043 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
2044 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
2045 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
2046 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
2047 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
2048 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
2049 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
2050 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
2051 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
2052 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
2053 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
2054 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
2055 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
2056 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
2057 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
2058 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
2059 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
2060 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
2061 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
2062 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
2063 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
2064 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
2065 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
2066 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
2067 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
2068 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
2069 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
2070 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
2072 if (developer.integer)
2073 Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
2076 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
2080 Mem_Free(vertexstring);
2082 Mem_Free(geometrystring);
2084 Mem_Free(fragmentstring);
2087 void R_GLSL_Restart_f(void)
2089 unsigned int i, limit;
2090 r_glsl_permutation_t *p;
2091 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
2092 for (i = 0;i < limit;i++)
2094 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
2096 GL_Backend_FreeProgram(p->program);
2097 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
2100 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2103 void R_GLSL_DumpShader_f(void)
2107 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
2110 Con_Printf("failed to write to glsl/default.glsl\n");
2114 FS_Print(file, "/* The engine may define the following macros:\n");
2115 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2116 for (i = 0;i < SHADERMODE_COUNT;i++)
2117 FS_Print(file, shadermodeinfo[i].pretext);
2118 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2119 FS_Print(file, shaderpermutationinfo[i].pretext);
2120 FS_Print(file, "*/\n");
2121 FS_Print(file, builtinshaderstring);
2124 Con_Printf("glsl/default.glsl written\n");
2127 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
2129 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2130 if (r_glsl_permutation != perm)
2132 r_glsl_permutation = perm;
2133 if (!r_glsl_permutation->program)
2135 if (!r_glsl_permutation->compiled)
2136 R_GLSL_CompilePermutation(perm, mode, permutation);
2137 if (!r_glsl_permutation->program)
2139 // remove features until we find a valid permutation
2141 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2143 // reduce i more quickly whenever it would not remove any bits
2144 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2145 if (!(permutation & j))
2148 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2149 if (!r_glsl_permutation->compiled)
2150 R_GLSL_CompilePermutation(perm, mode, permutation);
2151 if (r_glsl_permutation->program)
2154 if (i >= SHADERPERMUTATION_COUNT)
2156 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2157 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2158 qglUseProgramObjectARB(0);CHECKGLERROR
2159 return; // no bit left to clear, entire mode is broken
2164 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2168 void R_SetupGenericShader(qboolean usetexture)
2170 switch(vid.renderpath)
2172 case RENDERPATH_GL20:
2173 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2175 case RENDERPATH_GL13:
2176 case RENDERPATH_GL11:
2181 void R_SetupGenericTwoTextureShader(int texturemode)
2183 switch (vid.renderpath)
2185 case RENDERPATH_GL20:
2186 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))));
2188 case RENDERPATH_GL13:
2189 case RENDERPATH_GL11:
2190 R_Mesh_TexCombine(1, GL_DECAL, GL_DECAL, 1, 1);
2195 void R_SetupDepthOrShadowShader(void)
2197 switch (vid.renderpath)
2199 case RENDERPATH_GL20:
2200 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2202 case RENDERPATH_GL13:
2204 case RENDERPATH_GL11:
2209 void R_SetupShowDepthShader(void)
2211 switch (vid.renderpath)
2213 case RENDERPATH_GL20:
2214 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2216 case RENDERPATH_GL13:
2218 case RENDERPATH_GL11:
2223 extern qboolean r_shadow_usingdeferredprepass;
2224 extern cvar_t r_shadow_deferred_8bitrange;
2225 extern rtexture_t *r_shadow_attenuationgradienttexture;
2226 extern rtexture_t *r_shadow_attenuation2dtexture;
2227 extern rtexture_t *r_shadow_attenuation3dtexture;
2228 extern qboolean r_shadow_usingshadowmaprect;
2229 extern qboolean r_shadow_usingshadowmapcube;
2230 extern qboolean r_shadow_usingshadowmap2d;
2231 extern float r_shadow_shadowmap_texturescale[2];
2232 extern float r_shadow_shadowmap_parameters[4];
2233 extern qboolean r_shadow_shadowmapvsdct;
2234 extern qboolean r_shadow_shadowmapsampler;
2235 extern int r_shadow_shadowmappcf;
2236 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2238 // select a permutation of the lighting shader appropriate to this
2239 // combination of texture, entity, light source, and fogging, only use the
2240 // minimum features necessary to avoid wasting rendering time in the
2241 // fragment shader on features that are not being used
2242 unsigned int permutation = 0;
2243 unsigned int mode = 0;
2245 // TODO: implement geometry-shader based shadow volumes someday
2246 if (r_glsl_offsetmapping.integer)
2248 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2249 if (r_glsl_offsetmapping_reliefmapping.integer)
2250 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2252 if (rsurfacepass == RSURFPASS_BACKGROUND)
2254 // distorted background
2255 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2256 mode = SHADERMODE_WATER;
2258 mode = SHADERMODE_REFRACTION;
2260 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2262 // normalmap (deferred prepass), may use alpha test on diffuse
2263 mode = SHADERMODE_DEFERREDGEOMETRY;
2264 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2265 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2266 if (r_glsl_offsetmapping.integer)
2268 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2269 if (r_glsl_offsetmapping_reliefmapping.integer)
2270 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2273 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2276 mode = SHADERMODE_LIGHTSOURCE;
2277 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2278 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2279 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2280 permutation |= SHADERPERMUTATION_CUBEFILTER;
2281 if (diffusescale > 0)
2282 permutation |= SHADERPERMUTATION_DIFFUSE;
2283 if (specularscale > 0)
2284 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2285 if (r_refdef.fogenabled)
2286 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2287 if (rsurface.texture->colormapping)
2288 permutation |= SHADERPERMUTATION_COLORMAPPING;
2289 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2291 if (r_shadow_usingshadowmaprect)
2292 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2293 if (r_shadow_usingshadowmap2d)
2294 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2295 if (r_shadow_usingshadowmapcube)
2296 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2297 else if(r_shadow_shadowmapvsdct)
2298 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2300 if (r_shadow_shadowmapsampler)
2301 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2302 if (r_shadow_shadowmappcf > 1)
2303 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2304 else if (r_shadow_shadowmappcf)
2305 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2308 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2310 // unshaded geometry (fullbright or ambient model lighting)
2311 mode = SHADERMODE_FLATCOLOR;
2312 ambientscale = diffusescale = specularscale = 0;
2313 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2314 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2315 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2316 permutation |= SHADERPERMUTATION_GLOW;
2317 if (r_refdef.fogenabled)
2318 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2319 if (rsurface.texture->colormapping)
2320 permutation |= SHADERPERMUTATION_COLORMAPPING;
2321 if (r_glsl_offsetmapping.integer)
2323 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2324 if (r_glsl_offsetmapping_reliefmapping.integer)
2325 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2327 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2328 permutation |= SHADERPERMUTATION_REFLECTION;
2330 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2332 // directional model lighting
2333 mode = SHADERMODE_LIGHTDIRECTION;
2334 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2335 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2336 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2337 permutation |= SHADERPERMUTATION_GLOW;
2338 permutation |= SHADERPERMUTATION_DIFFUSE;
2339 if (specularscale > 0)
2340 permutation |= SHADERPERMUTATION_SPECULAR;
2341 if (r_refdef.fogenabled)
2342 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2343 if (rsurface.texture->colormapping)
2344 permutation |= SHADERPERMUTATION_COLORMAPPING;
2345 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2346 permutation |= SHADERPERMUTATION_REFLECTION;
2347 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2348 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2350 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2352 // ambient model lighting
2353 mode = SHADERMODE_LIGHTDIRECTION;
2354 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2355 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2356 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2357 permutation |= SHADERPERMUTATION_GLOW;
2358 if (r_refdef.fogenabled)
2359 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2360 if (rsurface.texture->colormapping)
2361 permutation |= SHADERPERMUTATION_COLORMAPPING;
2362 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2363 permutation |= SHADERPERMUTATION_REFLECTION;
2364 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2365 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2370 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2372 // deluxemapping (light direction texture)
2373 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2374 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2376 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2377 permutation |= SHADERPERMUTATION_DIFFUSE;
2378 if (specularscale > 0)
2379 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2381 else if (r_glsl_deluxemapping.integer >= 2)
2383 // fake deluxemapping (uniform light direction in tangentspace)
2384 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2385 permutation |= SHADERPERMUTATION_DIFFUSE;
2386 if (specularscale > 0)
2387 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2389 else if (rsurface.uselightmaptexture)
2391 // ordinary lightmapping (q1bsp, q3bsp)
2392 mode = SHADERMODE_LIGHTMAP;
2396 // ordinary vertex coloring (q3bsp)
2397 mode = SHADERMODE_VERTEXCOLOR;
2399 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2400 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2401 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2402 permutation |= SHADERPERMUTATION_GLOW;
2403 if (r_refdef.fogenabled)
2404 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2405 if (rsurface.texture->colormapping)
2406 permutation |= SHADERPERMUTATION_COLORMAPPING;
2407 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2408 permutation |= SHADERPERMUTATION_REFLECTION;
2409 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2410 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2412 if(permutation & SHADERPERMUTATION_SPECULAR)
2413 if(r_shadow_glossexact.integer)
2414 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2415 if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
2416 permutation |= SHADERPERMUTATION_ALPHAKILL;
2417 R_SetupShader_SetPermutation(mode, permutation);
2418 if (mode == SHADERMODE_LIGHTSOURCE)
2420 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2421 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2422 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2423 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
2424 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
2425 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
2427 // additive passes are only darkened by fog, not tinted
2428 if (r_glsl_permutation->loc_FogColor >= 0)
2429 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2430 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]);
2431 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]);
2432 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2436 if (mode == SHADERMODE_FLATCOLOR)
2438 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
2440 else if (mode == SHADERMODE_LIGHTDIRECTION)
2442 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);
2443 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
2444 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
2445 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
2446 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2447 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2448 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]);
2452 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
2453 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2454 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
2455 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2456 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2458 // additive passes are only darkened by fog, not tinted
2459 if (r_glsl_permutation->loc_FogColor >= 0)
2461 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2462 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2464 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2466 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);
2467 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]);
2468 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]);
2469 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2470 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2471 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2472 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2473 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2475 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2476 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2477 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2478 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
2479 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2480 if (r_glsl_permutation->loc_Color_Pants >= 0)
2482 if (rsurface.texture->currentskinframe->pants)
2483 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2485 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2487 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2489 if (rsurface.texture->currentskinframe->shirt)
2490 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2492 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2494 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]);
2495 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2496 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2497 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2498 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2499 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2503 void R_SetupDeferredLightShader(const rtlight_t *rtlight)
2505 // select a permutation of the lighting shader appropriate to this
2506 // combination of texture, entity, light source, and fogging, only use the
2507 // minimum features necessary to avoid wasting rendering time in the
2508 // fragment shader on features that are not being used
2509 unsigned int permutation = 0;
2510 unsigned int mode = 0;
2511 const float *lightcolorbase = rtlight->currentcolor;
2512 float ambientscale = rtlight->ambientscale;
2513 float diffusescale = rtlight->diffusescale;
2514 float specularscale = rtlight->specularscale;
2515 // this is the location of the light in view space
2516 vec3_t viewlightorigin;
2517 // this transforms from view space (camera) to light space (cubemap)
2518 matrix4x4_t viewtolight;
2519 matrix4x4_t lighttoview;
2520 float viewtolight16f[16];
2521 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2523 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2524 if (rtlight->currentcubemap != r_texture_whitecube)
2525 permutation |= SHADERPERMUTATION_CUBEFILTER;
2526 if (diffusescale > 0)
2527 permutation |= SHADERPERMUTATION_DIFFUSE;
2528 if (specularscale > 0)
2530 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2531 if (r_shadow_glossexact.integer)
2532 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2534 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2536 if (r_shadow_usingshadowmaprect)
2537 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2538 if (r_shadow_usingshadowmap2d)
2539 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2540 if (r_shadow_usingshadowmapcube)
2541 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2542 else if(r_shadow_shadowmapvsdct)
2543 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2545 if (r_shadow_shadowmapsampler)
2546 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2547 if (r_shadow_shadowmappcf > 1)
2548 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2549 else if (r_shadow_shadowmappcf)
2550 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2552 R_SetupShader_SetPermutation(mode, permutation);
2553 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2554 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2555 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2556 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2557 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2558 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight, 1, false, viewtolight16f);
2559 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2560 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2561 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2562 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]);
2563 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]);
2564 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2565 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2568 #define SKINFRAME_HASH 1024
2572 int loadsequence; // incremented each level change
2573 memexpandablearray_t array;
2574 skinframe_t *hash[SKINFRAME_HASH];
2577 r_skinframe_t r_skinframe;
2579 void R_SkinFrame_PrepareForPurge(void)
2581 r_skinframe.loadsequence++;
2582 // wrap it without hitting zero
2583 if (r_skinframe.loadsequence >= 200)
2584 r_skinframe.loadsequence = 1;
2587 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2591 // mark the skinframe as used for the purging code
2592 skinframe->loadsequence = r_skinframe.loadsequence;
2595 void R_SkinFrame_Purge(void)
2599 for (i = 0;i < SKINFRAME_HASH;i++)
2601 for (s = r_skinframe.hash[i];s;s = s->next)
2603 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2605 if (s->merged == s->base)
2607 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2608 R_PurgeTexture(s->stain );s->stain = NULL;
2609 R_PurgeTexture(s->merged);s->merged = NULL;
2610 R_PurgeTexture(s->base );s->base = NULL;
2611 R_PurgeTexture(s->pants );s->pants = NULL;
2612 R_PurgeTexture(s->shirt );s->shirt = NULL;
2613 R_PurgeTexture(s->nmap );s->nmap = NULL;
2614 R_PurgeTexture(s->gloss );s->gloss = NULL;
2615 R_PurgeTexture(s->glow );s->glow = NULL;
2616 R_PurgeTexture(s->fog );s->fog = NULL;
2617 s->loadsequence = 0;
2623 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2625 char basename[MAX_QPATH];
2627 Image_StripImageExtension(name, basename, sizeof(basename));
2629 if( last == NULL ) {
2631 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2632 item = r_skinframe.hash[hashindex];
2637 // linearly search through the hash bucket
2638 for( ; item ; item = item->next ) {
2639 if( !strcmp( item->basename, basename ) ) {
2646 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2650 char basename[MAX_QPATH];
2652 Image_StripImageExtension(name, basename, sizeof(basename));
2654 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2655 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2656 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2660 rtexture_t *dyntexture;
2661 // check whether its a dynamic texture
2662 dyntexture = CL_GetDynTexture( basename );
2663 if (!add && !dyntexture)
2665 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2666 memset(item, 0, sizeof(*item));
2667 strlcpy(item->basename, basename, sizeof(item->basename));
2668 item->base = dyntexture; // either NULL or dyntexture handle
2669 item->textureflags = textureflags;
2670 item->comparewidth = comparewidth;
2671 item->compareheight = compareheight;
2672 item->comparecrc = comparecrc;
2673 item->next = r_skinframe.hash[hashindex];
2674 r_skinframe.hash[hashindex] = item;
2676 else if( item->base == NULL )
2678 rtexture_t *dyntexture;
2679 // check whether its a dynamic texture
2680 // 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]
2681 dyntexture = CL_GetDynTexture( basename );
2682 item->base = dyntexture; // either NULL or dyntexture handle
2685 R_SkinFrame_MarkUsed(item);
2689 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2691 unsigned long long avgcolor[5], wsum; \
2699 for(pix = 0; pix < cnt; ++pix) \
2702 for(comp = 0; comp < 3; ++comp) \
2704 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2707 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2709 for(comp = 0; comp < 3; ++comp) \
2710 avgcolor[comp] += getpixel * w; \
2713 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2714 avgcolor[4] += getpixel; \
2716 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2718 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2719 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2720 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2721 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2724 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2727 unsigned char *pixels;
2728 unsigned char *bumppixels;
2729 unsigned char *basepixels = NULL;
2730 int basepixels_width;
2731 int basepixels_height;
2732 skinframe_t *skinframe;
2734 if (cls.state == ca_dedicated)
2737 // return an existing skinframe if already loaded
2738 // if loading of the first image fails, don't make a new skinframe as it
2739 // would cause all future lookups of this to be missing
2740 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2741 if (skinframe && skinframe->base)
2744 basepixels = loadimagepixelsbgra(name, complain, true);
2745 if (basepixels == NULL)
2748 if (developer_loading.integer)
2749 Con_Printf("loading skin \"%s\"\n", name);
2751 // we've got some pixels to store, so really allocate this new texture now
2753 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2754 skinframe->stain = NULL;
2755 skinframe->merged = NULL;
2756 skinframe->base = r_texture_notexture;
2757 skinframe->pants = NULL;
2758 skinframe->shirt = NULL;
2759 skinframe->nmap = r_texture_blanknormalmap;
2760 skinframe->gloss = NULL;
2761 skinframe->glow = NULL;
2762 skinframe->fog = NULL;
2763 skinframe->hasalpha = false;
2765 basepixels_width = image_width;
2766 basepixels_height = image_height;
2767 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);
2769 if (textureflags & TEXF_ALPHA)
2771 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2773 if (basepixels[j] < 255)
2775 skinframe->hasalpha = true;
2779 if (r_loadfog && skinframe->hasalpha)
2781 // has transparent pixels
2782 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2783 for (j = 0;j < image_width * image_height * 4;j += 4)
2788 pixels[j+3] = basepixels[j+3];
2790 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);
2795 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2796 //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]);
2798 // _norm is the name used by tenebrae and has been adopted as standard
2799 if (r_loadnormalmap)
2801 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2803 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);
2807 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2809 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2810 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2811 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);
2813 Mem_Free(bumppixels);
2815 else if (r_shadow_bumpscale_basetexture.value > 0)
2817 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2818 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2819 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);
2823 // _luma is supported for tenebrae compatibility
2824 // (I think it's a very stupid name, but oh well)
2825 // _glow is the preferred name
2826 if ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2827 if (r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false))) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2828 if ((pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false))) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2829 if ((pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false))) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2832 Mem_Free(basepixels);
2837 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2838 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2841 unsigned char *temp1, *temp2;
2842 skinframe_t *skinframe;
2844 if (cls.state == ca_dedicated)
2847 // if already loaded just return it, otherwise make a new skinframe
2848 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2849 if (skinframe && skinframe->base)
2852 skinframe->stain = NULL;
2853 skinframe->merged = NULL;
2854 skinframe->base = r_texture_notexture;
2855 skinframe->pants = NULL;
2856 skinframe->shirt = NULL;
2857 skinframe->nmap = r_texture_blanknormalmap;
2858 skinframe->gloss = NULL;
2859 skinframe->glow = NULL;
2860 skinframe->fog = NULL;
2861 skinframe->hasalpha = false;
2863 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2867 if (developer_loading.integer)
2868 Con_Printf("loading 32bit skin \"%s\"\n", name);
2870 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2872 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2873 temp2 = temp1 + width * height * 4;
2874 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2875 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2878 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2879 if (textureflags & TEXF_ALPHA)
2881 for (i = 3;i < width * height * 4;i += 4)
2883 if (skindata[i] < 255)
2885 skinframe->hasalpha = true;
2889 if (r_loadfog && skinframe->hasalpha)
2891 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2892 memcpy(fogpixels, skindata, width * height * 4);
2893 for (i = 0;i < width * height * 4;i += 4)
2894 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2895 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2896 Mem_Free(fogpixels);
2900 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2901 //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]);
2906 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2910 skinframe_t *skinframe;
2912 if (cls.state == ca_dedicated)
2915 // if already loaded just return it, otherwise make a new skinframe
2916 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2917 if (skinframe && skinframe->base)
2920 skinframe->stain = NULL;
2921 skinframe->merged = NULL;
2922 skinframe->base = r_texture_notexture;
2923 skinframe->pants = NULL;
2924 skinframe->shirt = NULL;
2925 skinframe->nmap = r_texture_blanknormalmap;
2926 skinframe->gloss = NULL;
2927 skinframe->glow = NULL;
2928 skinframe->fog = NULL;
2929 skinframe->hasalpha = false;
2931 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2935 if (developer_loading.integer)
2936 Con_Printf("loading quake skin \"%s\"\n", name);
2938 // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
2939 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
2940 memcpy(skinframe->qpixels, skindata, width*height);
2941 skinframe->qwidth = width;
2942 skinframe->qheight = height;
2945 for (i = 0;i < width * height;i++)
2946 featuresmask |= palette_featureflags[skindata[i]];
2948 skinframe->hasalpha = false;
2949 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2950 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2951 skinframe->qgeneratemerged = true;
2952 skinframe->qgeneratebase = skinframe->qhascolormapping;
2953 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2955 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2956 //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]);
2961 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2965 unsigned char *skindata;
2967 if (!skinframe->qpixels)
2970 if (!skinframe->qhascolormapping)
2971 colormapped = false;
2975 if (!skinframe->qgeneratebase)
2980 if (!skinframe->qgeneratemerged)
2984 width = skinframe->qwidth;
2985 height = skinframe->qheight;
2986 skindata = skinframe->qpixels;
2988 if (skinframe->qgeneratenmap)
2990 unsigned char *temp1, *temp2;
2991 skinframe->qgeneratenmap = false;
2992 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2993 temp2 = temp1 + width * height * 4;
2994 // use either a custom palette or the quake palette
2995 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2996 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2997 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
3001 if (skinframe->qgenerateglow)
3003 skinframe->qgenerateglow = false;
3004 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
3009 skinframe->qgeneratebase = false;
3010 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3011 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
3012 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
3016 skinframe->qgeneratemerged = false;
3017 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3020 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3022 Mem_Free(skinframe->qpixels);
3023 skinframe->qpixels = NULL;
3027 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)
3030 skinframe_t *skinframe;
3032 if (cls.state == ca_dedicated)
3035 // if already loaded just return it, otherwise make a new skinframe
3036 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3037 if (skinframe && skinframe->base)
3040 skinframe->stain = NULL;
3041 skinframe->merged = NULL;
3042 skinframe->base = r_texture_notexture;
3043 skinframe->pants = NULL;
3044 skinframe->shirt = NULL;
3045 skinframe->nmap = r_texture_blanknormalmap;
3046 skinframe->gloss = NULL;
3047 skinframe->glow = NULL;
3048 skinframe->fog = NULL;
3049 skinframe->hasalpha = false;
3051 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3055 if (developer_loading.integer)
3056 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3058 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
3059 if (textureflags & TEXF_ALPHA)
3061 for (i = 0;i < width * height;i++)
3063 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3065 skinframe->hasalpha = true;
3069 if (r_loadfog && skinframe->hasalpha)
3070 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
3073 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3074 //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]);
3079 skinframe_t *R_SkinFrame_LoadMissing(void)
3081 skinframe_t *skinframe;
3083 if (cls.state == ca_dedicated)
3086 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
3087 skinframe->stain = NULL;
3088 skinframe->merged = NULL;
3089 skinframe->base = r_texture_notexture;
3090 skinframe->pants = NULL;
3091 skinframe->shirt = NULL;
3092 skinframe->nmap = r_texture_blanknormalmap;
3093 skinframe->gloss = NULL;
3094 skinframe->glow = NULL;
3095 skinframe->fog = NULL;
3096 skinframe->hasalpha = false;
3098 skinframe->avgcolor[0] = rand() / RAND_MAX;
3099 skinframe->avgcolor[1] = rand() / RAND_MAX;
3100 skinframe->avgcolor[2] = rand() / RAND_MAX;
3101 skinframe->avgcolor[3] = 1;
3106 void R_Main_FreeViewCache(void)
3108 if (r_refdef.viewcache.entityvisible)
3109 Mem_Free(r_refdef.viewcache.entityvisible);
3110 if (r_refdef.viewcache.world_pvsbits)
3111 Mem_Free(r_refdef.viewcache.world_pvsbits);
3112 if (r_refdef.viewcache.world_leafvisible)
3113 Mem_Free(r_refdef.viewcache.world_leafvisible);
3114 if (r_refdef.viewcache.world_surfacevisible)
3115 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3116 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3119 void R_Main_ResizeViewCache(void)
3121 int numentities = r_refdef.scene.numentities;
3122 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3123 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3124 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3125 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3126 if (r_refdef.viewcache.maxentities < numentities)
3128 r_refdef.viewcache.maxentities = numentities;
3129 if (r_refdef.viewcache.entityvisible)
3130 Mem_Free(r_refdef.viewcache.entityvisible);
3131 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3133 if (r_refdef.viewcache.world_numclusters != numclusters)
3135 r_refdef.viewcache.world_numclusters = numclusters;
3136 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3137 if (r_refdef.viewcache.world_pvsbits)
3138 Mem_Free(r_refdef.viewcache.world_pvsbits);
3139 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3141 if (r_refdef.viewcache.world_numleafs != numleafs)
3143 r_refdef.viewcache.world_numleafs = numleafs;
3144 if (r_refdef.viewcache.world_leafvisible)
3145 Mem_Free(r_refdef.viewcache.world_leafvisible);
3146 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3148 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3150 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3151 if (r_refdef.viewcache.world_surfacevisible)
3152 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3153 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3157 extern rtexture_t *loadingscreentexture;
3158 void gl_main_start(void)
3160 loadingscreentexture = NULL;
3161 r_texture_blanknormalmap = NULL;
3162 r_texture_white = NULL;
3163 r_texture_grey128 = NULL;
3164 r_texture_black = NULL;
3165 r_texture_whitecube = NULL;
3166 r_texture_normalizationcube = NULL;
3167 r_texture_fogattenuation = NULL;
3168 r_texture_gammaramps = NULL;
3170 switch(vid.renderpath)
3172 case RENDERPATH_GL20:
3173 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3174 Cvar_SetValueQuick(&gl_combine, 1);
3175 Cvar_SetValueQuick(&r_glsl, 1);
3176 r_loadnormalmap = true;
3180 case RENDERPATH_GL13:
3181 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3182 Cvar_SetValueQuick(&gl_combine, 1);
3183 Cvar_SetValueQuick(&r_glsl, 0);
3184 r_loadnormalmap = false;
3185 r_loadgloss = false;
3188 case RENDERPATH_GL11:
3189 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3190 Cvar_SetValueQuick(&gl_combine, 0);
3191 Cvar_SetValueQuick(&r_glsl, 0);
3192 r_loadnormalmap = false;
3193 r_loadgloss = false;
3199 R_FrameData_Reset();
3203 memset(r_queries, 0, sizeof(r_queries));
3205 r_qwskincache = NULL;
3206 r_qwskincache_size = 0;
3208 // set up r_skinframe loading system for textures
3209 memset(&r_skinframe, 0, sizeof(r_skinframe));
3210 r_skinframe.loadsequence = 1;
3211 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3213 r_main_texturepool = R_AllocTexturePool();
3214 R_BuildBlankTextures();
3216 if (vid.support.arb_texture_cube_map)
3219 R_BuildNormalizationCube();
3221 r_texture_fogattenuation = NULL;
3222 r_texture_gammaramps = NULL;
3223 //r_texture_fogintensity = NULL;
3224 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3225 memset(&r_waterstate, 0, sizeof(r_waterstate));
3226 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3227 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3228 memset(&r_svbsp, 0, sizeof (r_svbsp));
3230 r_refdef.fogmasktable_density = 0;
3233 void gl_main_shutdown(void)
3236 R_FrameData_Reset();
3238 R_Main_FreeViewCache();
3241 qglDeleteQueriesARB(r_maxqueries, r_queries);
3245 memset(r_queries, 0, sizeof(r_queries));
3247 r_qwskincache = NULL;
3248 r_qwskincache_size = 0;
3250 // clear out the r_skinframe state
3251 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3252 memset(&r_skinframe, 0, sizeof(r_skinframe));
3255 Mem_Free(r_svbsp.nodes);
3256 memset(&r_svbsp, 0, sizeof (r_svbsp));
3257 R_FreeTexturePool(&r_main_texturepool);
3258 loadingscreentexture = NULL;
3259 r_texture_blanknormalmap = NULL;
3260 r_texture_white = NULL;
3261 r_texture_grey128 = NULL;
3262 r_texture_black = NULL;
3263 r_texture_whitecube = NULL;
3264 r_texture_normalizationcube = NULL;
3265 r_texture_fogattenuation = NULL;
3266 r_texture_gammaramps = NULL;
3267 //r_texture_fogintensity = NULL;
3268 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3269 memset(&r_waterstate, 0, sizeof(r_waterstate));
3273 extern void CL_ParseEntityLump(char *entitystring);
3274 void gl_main_newmap(void)
3276 // FIXME: move this code to client
3278 char *entities, entname[MAX_QPATH];
3280 Mem_Free(r_qwskincache);
3281 r_qwskincache = NULL;
3282 r_qwskincache_size = 0;
3285 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
3286 l = (int)strlen(entname) - 4;
3287 if (l >= 0 && !strcmp(entname + l, ".bsp"))
3289 memcpy(entname + l, ".ent", 5);
3290 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3292 CL_ParseEntityLump(entities);
3297 if (cl.worldmodel->brush.entities)
3298 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3300 R_Main_FreeViewCache();
3302 R_FrameData_Reset();
3305 void GL_Main_Init(void)
3307 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3309 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3310 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3311 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3312 if (gamemode == GAME_NEHAHRA)
3314 Cvar_RegisterVariable (&gl_fogenable);
3315 Cvar_RegisterVariable (&gl_fogdensity);
3316 Cvar_RegisterVariable (&gl_fogred);
3317 Cvar_RegisterVariable (&gl_foggreen);
3318 Cvar_RegisterVariable (&gl_fogblue);
3319 Cvar_RegisterVariable (&gl_fogstart);
3320 Cvar_RegisterVariable (&gl_fogend);
3321 Cvar_RegisterVariable (&gl_skyclip);
3323 Cvar_RegisterVariable(&r_motionblur);
3324 Cvar_RegisterVariable(&r_motionblur_maxblur);
3325 Cvar_RegisterVariable(&r_motionblur_bmin);
3326 Cvar_RegisterVariable(&r_motionblur_vmin);
3327 Cvar_RegisterVariable(&r_motionblur_vmax);
3328 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3329 Cvar_RegisterVariable(&r_motionblur_randomize);
3330 Cvar_RegisterVariable(&r_damageblur);
3331 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3332 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3333 Cvar_RegisterVariable(&r_equalize_entities_by);
3334 Cvar_RegisterVariable(&r_equalize_entities_to);
3335 Cvar_RegisterVariable(&r_depthfirst);
3336 Cvar_RegisterVariable(&r_useinfinitefarclip);
3337 Cvar_RegisterVariable(&r_farclip_base);
3338 Cvar_RegisterVariable(&r_farclip_world);
3339 Cvar_RegisterVariable(&r_nearclip);
3340 Cvar_RegisterVariable(&r_showbboxes);
3341 Cvar_RegisterVariable(&r_showsurfaces);
3342 Cvar_RegisterVariable(&r_showtris);
3343 Cvar_RegisterVariable(&r_shownormals);
3344 Cvar_RegisterVariable(&r_showlighting);
3345 Cvar_RegisterVariable(&r_showshadowvolumes);
3346 Cvar_RegisterVariable(&r_showcollisionbrushes);
3347 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3348 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3349 Cvar_RegisterVariable(&r_showdisabledepthtest);
3350 Cvar_RegisterVariable(&r_drawportals);
3351 Cvar_RegisterVariable(&r_drawentities);
3352 Cvar_RegisterVariable(&r_cullentities_trace);
3353 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3354 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3355 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3356 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3357 Cvar_RegisterVariable(&r_drawviewmodel);
3358 Cvar_RegisterVariable(&r_speeds);
3359 Cvar_RegisterVariable(&r_fullbrights);
3360 Cvar_RegisterVariable(&r_wateralpha);
3361 Cvar_RegisterVariable(&r_dynamic);
3362 Cvar_RegisterVariable(&r_fullbright);
3363 Cvar_RegisterVariable(&r_shadows);
3364 Cvar_RegisterVariable(&r_shadows_darken);
3365 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3366 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3367 Cvar_RegisterVariable(&r_shadows_throwdistance);
3368 Cvar_RegisterVariable(&r_shadows_throwdirection);
3369 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3370 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3371 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3372 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3373 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3374 Cvar_RegisterVariable(&r_fog_exp2);
3375 Cvar_RegisterVariable(&r_drawfog);
3376 Cvar_RegisterVariable(&r_transparentdepthmasking);
3377 Cvar_RegisterVariable(&r_textureunits);
3378 Cvar_RegisterVariable(&gl_combine);
3379 Cvar_RegisterVariable(&r_glsl);
3380 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3381 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3382 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3383 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3384 Cvar_RegisterVariable(&r_glsl_postprocess);
3385 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3386 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3387 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3388 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3389 Cvar_RegisterVariable(&r_water);
3390 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3391 Cvar_RegisterVariable(&r_water_clippingplanebias);
3392 Cvar_RegisterVariable(&r_water_refractdistort);
3393 Cvar_RegisterVariable(&r_water_reflectdistort);
3394 Cvar_RegisterVariable(&r_lerpsprites);
3395 Cvar_RegisterVariable(&r_lerpmodels);
3396 Cvar_RegisterVariable(&r_lerplightstyles);
3397 Cvar_RegisterVariable(&r_waterscroll);
3398 Cvar_RegisterVariable(&r_bloom);
3399 Cvar_RegisterVariable(&r_bloom_colorscale);
3400 Cvar_RegisterVariable(&r_bloom_brighten);
3401 Cvar_RegisterVariable(&r_bloom_blur);
3402 Cvar_RegisterVariable(&r_bloom_resolution);
3403 Cvar_RegisterVariable(&r_bloom_colorexponent);
3404 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3405 Cvar_RegisterVariable(&r_hdr);
3406 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3407 Cvar_RegisterVariable(&r_hdr_glowintensity);
3408 Cvar_RegisterVariable(&r_hdr_range);
3409 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3410 Cvar_RegisterVariable(&developer_texturelogging);
3411 Cvar_RegisterVariable(&gl_lightmaps);
3412 Cvar_RegisterVariable(&r_test);
3413 Cvar_RegisterVariable(&r_batchmode);
3414 Cvar_RegisterVariable(&r_glsl_saturation);
3415 Cvar_RegisterVariable(&r_framedatasize);
3416 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3417 Cvar_SetValue("r_fullbrights", 0);
3418 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3420 Cvar_RegisterVariable(&r_track_sprites);
3421 Cvar_RegisterVariable(&r_track_sprites_flags);
3422 Cvar_RegisterVariable(&r_track_sprites_scalew);
3423 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3426 extern void R_Textures_Init(void);
3427 extern void GL_Draw_Init(void);
3428 extern void GL_Main_Init(void);
3429 extern void R_Shadow_Init(void);
3430 extern void R_Sky_Init(void);
3431 extern void GL_Surf_Init(void);
3432 extern void R_Particles_Init(void);
3433 extern void R_Explosion_Init(void);
3434 extern void gl_backend_init(void);
3435 extern void Sbar_Init(void);
3436 extern void R_LightningBeams_Init(void);
3437 extern void Mod_RenderInit(void);
3439 void Render_Init(void)
3451 R_LightningBeams_Init();
3460 extern char *ENGINE_EXTENSIONS;
3463 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3464 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3465 gl_version = (const char *)qglGetString(GL_VERSION);
3466 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3470 if (!gl_platformextensions)
3471 gl_platformextensions = "";
3473 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3474 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3475 Con_Printf("GL_VERSION: %s\n", gl_version);
3476 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3477 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3479 VID_CheckExtensions();
3481 // LordHavoc: report supported extensions
3482 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3484 // clear to black (loading plaque will be seen over this)
3486 qglClearColor(0,0,0,1);CHECKGLERROR
3487 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3490 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3494 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3496 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3499 p = r_refdef.view.frustum + i;
3504 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3508 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3512 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3516 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3520 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3524 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3528 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3532 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3540 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3544 for (i = 0;i < numplanes;i++)
3551 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3555 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3559 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3563 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3567 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3571 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3575 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3579 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3587 //==================================================================================
3589 // LordHavoc: this stores temporary data used within the same frame
3591 qboolean r_framedata_failed;
3592 static size_t r_framedata_size;
3593 static size_t r_framedata_current;
3594 static void *r_framedata_base;
3596 void R_FrameData_Reset(void)
3598 if (r_framedata_base);
3599 Mem_Free(r_framedata_base);
3600 r_framedata_base = NULL;
3601 r_framedata_size = 0;
3602 r_framedata_current = 0;
3603 r_framedata_failed = false;
3606 void R_FrameData_NewFrame(void)
3609 if (r_framedata_failed)
3610 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
3611 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
3612 wantedsize = bound(65536, wantedsize, 128*1024*1024);
3613 if (r_framedata_size != wantedsize)
3615 r_framedata_size = wantedsize;
3616 if (r_framedata_base);
3617 Mem_Free(r_framedata_base);
3618 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
3620 r_framedata_current = 0;
3621 r_framedata_failed = false;
3624 void *R_FrameData_Alloc(size_t size)
3628 // align to 16 byte boundary
3629 size = (size + 15) & ~15;
3630 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
3631 r_framedata_current += size;
3634 if (r_framedata_current > r_framedata_size)
3635 r_framedata_failed = true;
3637 // return NULL on everything after a failure
3638 if (r_framedata_failed)
3644 void *R_FrameData_Store(size_t size, void *data)
3646 void *d = R_FrameData_Alloc(size);
3648 memcpy(d, data, size);
3652 //==================================================================================
3654 // LordHavoc: animcache originally written by Echon, rewritten since then
3657 * Animation cache prevents re-generating mesh data for an animated model
3658 * multiple times in one frame for lighting, shadowing, reflections, etc.
3661 void R_AnimCache_Free(void)
3665 void R_AnimCache_ClearCache(void)
3668 entity_render_t *ent;
3670 for (i = 0;i < r_refdef.scene.numentities;i++)
3672 ent = r_refdef.scene.entities[i];
3673 ent->animcache_vertex3f = NULL;
3674 ent->animcache_normal3f = NULL;
3675 ent->animcache_svector3f = NULL;
3676 ent->animcache_tvector3f = NULL;
3680 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3682 dp_model_t *model = ent->model;
3684 // see if it's already cached this frame
3685 if (ent->animcache_vertex3f)
3687 // add normals/tangents if needed
3688 if (wantnormals || wanttangents)
3690 if (ent->animcache_normal3f)
3691 wantnormals = false;
3692 if (ent->animcache_svector3f)
3693 wanttangents = false;
3694 if (wantnormals || wanttangents)
3696 numvertices = model->surfmesh.num_vertices;
3698 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3701 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3702 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3704 if (!r_framedata_failed)
3705 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
3711 // see if this ent is worth caching
3712 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
3714 // get some memory for this entity and generate mesh data
3715 numvertices = model->surfmesh.num_vertices;
3716 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3718 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3721 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3722 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3724 if (!r_framedata_failed)
3725 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
3727 return !r_framedata_failed;
3730 void R_AnimCache_CacheVisibleEntities(void)
3733 qboolean wantnormals = !r_showsurfaces.integer;
3734 qboolean wanttangents = !r_showsurfaces.integer;
3736 switch(vid.renderpath)
3738 case RENDERPATH_GL20:
3740 case RENDERPATH_GL13:
3741 case RENDERPATH_GL11:
3742 wanttangents = false;
3746 // TODO: thread this
3747 // NOTE: R_PrepareRTLights() also caches entities
3749 for (i = 0;i < r_refdef.scene.numentities;i++)
3750 if (r_refdef.viewcache.entityvisible[i])
3751 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3753 if (r_shadows.integer)
3754 for (i = 0;i < r_refdef.scene.numentities;i++)
3755 if (!r_refdef.viewcache.entityvisible[i])
3756 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
3759 //==================================================================================
3761 static void R_View_UpdateEntityLighting (void)
3764 entity_render_t *ent;
3765 vec3_t tempdiffusenormal, avg;
3766 vec_t f, fa, fd, fdd;
3768 for (i = 0;i < r_refdef.scene.numentities;i++)
3770 ent = r_refdef.scene.entities[i];
3772 // skip unseen models
3773 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3777 if (ent->model && ent->model->brush.num_leafs)
3779 // TODO: use modellight for r_ambient settings on world?
3780 VectorSet(ent->modellight_ambient, 0, 0, 0);
3781 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3782 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3786 // fetch the lighting from the worldmodel data
3787 VectorClear(ent->modellight_ambient);
3788 VectorClear(ent->modellight_diffuse);
3789 VectorClear(tempdiffusenormal);
3790 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3793 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3794 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3795 if(ent->flags & RENDER_EQUALIZE)
3797 // first fix up ambient lighting...
3798 if(r_equalize_entities_minambient.value > 0)
3800 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3803 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3804 if(fa < r_equalize_entities_minambient.value * fd)
3807 // fa'/fd' = minambient
3808 // fa'+0.25*fd' = fa+0.25*fd
3810 // fa' = fd' * minambient
3811 // fd'*(0.25+minambient) = fa+0.25*fd
3813 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3814 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3816 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3817 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
3818 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3819 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3824 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3826 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3827 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3830 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3831 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3832 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3838 VectorSet(ent->modellight_ambient, 1, 1, 1);
3840 // move the light direction into modelspace coordinates for lighting code
3841 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3842 if(VectorLength2(ent->modellight_lightdir) == 0)
3843 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3844 VectorNormalize(ent->modellight_lightdir);
3848 #define MAX_LINEOFSIGHTTRACES 64
3850 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3853 vec3_t boxmins, boxmaxs;
3856 dp_model_t *model = r_refdef.scene.worldmodel;
3858 if (!model || !model->brush.TraceLineOfSight)
3861 // expand the box a little
3862 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3863 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3864 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3865 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3866 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3867 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3870 VectorCopy(eye, start);
3871 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3872 if (model->brush.TraceLineOfSight(model, start, end))
3875 // try various random positions
3876 for (i = 0;i < numsamples;i++)
3878 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3879 if (model->brush.TraceLineOfSight(model, start, end))
3887 static void R_View_UpdateEntityVisible (void)
3892 entity_render_t *ent;
3894 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3895 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3897 // worldmodel can check visibility
3898 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3899 for (i = 0;i < r_refdef.scene.numentities;i++)
3901 ent = r_refdef.scene.entities[i];
3902 if (!(ent->flags & renderimask))
3903 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)))
3904 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))
3905 r_refdef.viewcache.entityvisible[i] = true;
3907 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3909 for (i = 0;i < r_refdef.scene.numentities;i++)
3911 ent = r_refdef.scene.entities[i];
3912 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3914 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3916 continue; // temp entities do pvs only
3917 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3918 ent->last_trace_visibility = realtime;
3919 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3920 r_refdef.viewcache.entityvisible[i] = 0;
3927 // no worldmodel or it can't check visibility
3928 for (i = 0;i < r_refdef.scene.numentities;i++)
3930 ent = r_refdef.scene.entities[i];
3931 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));
3936 /// only used if skyrendermasked, and normally returns false
3937 int R_DrawBrushModelsSky (void)
3940 entity_render_t *ent;
3943 for (i = 0;i < r_refdef.scene.numentities;i++)
3945 if (!r_refdef.viewcache.entityvisible[i])
3947 ent = r_refdef.scene.entities[i];
3948 if (!ent->model || !ent->model->DrawSky)
3950 ent->model->DrawSky(ent);
3956 static void R_DrawNoModel(entity_render_t *ent);
3957 static void R_DrawModels(void)
3960 entity_render_t *ent;
3962 for (i = 0;i < r_refdef.scene.numentities;i++)
3964 if (!r_refdef.viewcache.entityvisible[i])
3966 ent = r_refdef.scene.entities[i];
3967 r_refdef.stats.entities++;
3968 if (ent->model && ent->model->Draw != NULL)
3969 ent->model->Draw(ent);
3975 static void R_DrawModelsDepth(void)
3978 entity_render_t *ent;
3980 for (i = 0;i < r_refdef.scene.numentities;i++)
3982 if (!r_refdef.viewcache.entityvisible[i])
3984 ent = r_refdef.scene.entities[i];
3985 if (ent->model && ent->model->DrawDepth != NULL)
3986 ent->model->DrawDepth(ent);
3990 static void R_DrawModelsDebug(void)
3993 entity_render_t *ent;
3995 for (i = 0;i < r_refdef.scene.numentities;i++)
3997 if (!r_refdef.viewcache.entityvisible[i])
3999 ent = r_refdef.scene.entities[i];
4000 if (ent->model && ent->model->DrawDebug != NULL)
4001 ent->model->DrawDebug(ent);
4005 static void R_DrawModelsAddWaterPlanes(void)
4008 entity_render_t *ent;
4010 for (i = 0;i < r_refdef.scene.numentities;i++)
4012 if (!r_refdef.viewcache.entityvisible[i])
4014 ent = r_refdef.scene.entities[i];
4015 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4016 ent->model->DrawAddWaterPlanes(ent);
4020 static void R_View_SetFrustum(void)
4023 double slopex, slopey;
4024 vec3_t forward, left, up, origin;
4026 // we can't trust r_refdef.view.forward and friends in reflected scenes
4027 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4030 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4031 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4032 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4033 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4034 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4035 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4036 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4037 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4038 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4039 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4040 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4041 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4045 zNear = r_refdef.nearclip;
4046 nudge = 1.0 - 1.0 / (1<<23);
4047 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4048 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4049 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4050 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4051 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4052 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4053 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4054 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4060 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4061 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4062 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4063 r_refdef.view.frustum[0].dist = m[15] - m[12];
4065 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4066 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4067 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4068 r_refdef.view.frustum[1].dist = m[15] + m[12];
4070 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4071 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4072 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4073 r_refdef.view.frustum[2].dist = m[15] - m[13];
4075 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4076 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4077 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4078 r_refdef.view.frustum[3].dist = m[15] + m[13];
4080 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4081 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4082 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4083 r_refdef.view.frustum[4].dist = m[15] - m[14];
4085 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4086 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4087 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4088 r_refdef.view.frustum[5].dist = m[15] + m[14];
4091 if (r_refdef.view.useperspective)
4093 slopex = 1.0 / r_refdef.view.frustum_x;
4094 slopey = 1.0 / r_refdef.view.frustum_y;
4095 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
4096 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
4097 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
4098 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
4099 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4101 // Leaving those out was a mistake, those were in the old code, and they
4102 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4103 // I couldn't reproduce it after adding those normalizations. --blub
4104 VectorNormalize(r_refdef.view.frustum[0].normal);
4105 VectorNormalize(r_refdef.view.frustum[1].normal);
4106 VectorNormalize(r_refdef.view.frustum[2].normal);
4107 VectorNormalize(r_refdef.view.frustum[3].normal);
4109 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4110 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]);
4111 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]);
4112 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]);
4113 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]);
4115 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4116 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4117 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4118 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4119 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4123 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4124 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4125 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4126 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
4127 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4128 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
4129 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
4130 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
4131 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
4132 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4134 r_refdef.view.numfrustumplanes = 5;
4136 if (r_refdef.view.useclipplane)
4138 r_refdef.view.numfrustumplanes = 6;
4139 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4142 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4143 PlaneClassify(r_refdef.view.frustum + i);
4145 // LordHavoc: note to all quake engine coders, Quake had a special case
4146 // for 90 degrees which assumed a square view (wrong), so I removed it,
4147 // Quake2 has it disabled as well.
4149 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4150 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4151 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4152 //PlaneClassify(&frustum[0]);
4154 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4155 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4156 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4157 //PlaneClassify(&frustum[1]);
4159 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4160 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4161 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4162 //PlaneClassify(&frustum[2]);
4164 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4165 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4166 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4167 //PlaneClassify(&frustum[3]);
4170 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4171 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4172 //PlaneClassify(&frustum[4]);
4175 void R_View_Update(void)
4177 R_Main_ResizeViewCache();
4178 R_View_SetFrustum();
4179 R_View_WorldVisibility(r_refdef.view.useclipplane);
4180 R_View_UpdateEntityVisible();
4181 R_View_UpdateEntityLighting();
4184 void R_SetupView(qboolean allowwaterclippingplane)
4186 const float *customclipplane = NULL;
4188 if (r_refdef.view.useclipplane && allowwaterclippingplane)
4190 // LordHavoc: couldn't figure out how to make this approach the
4191 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4192 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4193 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4194 dist = r_refdef.view.clipplane.dist;
4195 plane[0] = r_refdef.view.clipplane.normal[0];
4196 plane[1] = r_refdef.view.clipplane.normal[1];
4197 plane[2] = r_refdef.view.clipplane.normal[2];
4199 customclipplane = plane;
4202 if (!r_refdef.view.useperspective)
4203 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);
4204 else if (vid.stencil && r_useinfinitefarclip.integer)
4205 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);
4207 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);
4208 R_SetViewport(&r_refdef.view.viewport);
4211 void R_ResetViewRendering2D(void)
4213 r_viewport_t viewport;
4216 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
4217 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);
4218 R_SetViewport(&viewport);
4219 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
4220 GL_Color(1, 1, 1, 1);
4221 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4222 GL_BlendFunc(GL_ONE, GL_ZERO);
4223 GL_AlphaTest(false);
4224 GL_ScissorTest(false);
4225 GL_DepthMask(false);
4226 GL_DepthRange(0, 1);
4227 GL_DepthTest(false);
4228 R_Mesh_Matrix(&identitymatrix);
4229 R_Mesh_ResetTextureState();
4230 GL_PolygonOffset(0, 0);
4231 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4232 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4233 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4234 qglStencilMask(~0);CHECKGLERROR
4235 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4236 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4237 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
4238 R_SetupGenericShader(true);
4241 void R_ResetViewRendering3D(void)
4246 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
4247 GL_Color(1, 1, 1, 1);
4248 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4249 GL_BlendFunc(GL_ONE, GL_ZERO);
4250 GL_AlphaTest(false);
4251 GL_ScissorTest(true);
4253 GL_DepthRange(0, 1);
4255 R_Mesh_Matrix(&identitymatrix);
4256 R_Mesh_ResetTextureState();
4257 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4258 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4259 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4260 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4261 qglStencilMask(~0);CHECKGLERROR
4262 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4263 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4264 GL_CullFace(r_refdef.view.cullface_back);
4265 R_SetupGenericShader(true);
4268 void R_RenderScene(void);
4269 void R_RenderWaterPlanes(void);
4271 static void R_Water_StartFrame(void)
4274 int waterwidth, waterheight, texturewidth, textureheight;
4275 r_waterstate_waterplane_t *p;
4277 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
4280 switch(vid.renderpath)
4282 case RENDERPATH_GL20:
4284 case RENDERPATH_GL13:
4285 case RENDERPATH_GL11:
4289 // set waterwidth and waterheight to the water resolution that will be
4290 // used (often less than the screen resolution for faster rendering)
4291 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
4292 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
4294 // calculate desired texture sizes
4295 // can't use water if the card does not support the texture size
4296 if (!r_water.integer || r_showsurfaces.integer)
4297 texturewidth = textureheight = waterwidth = waterheight = 0;
4298 else if (vid.support.arb_texture_non_power_of_two)
4300 texturewidth = waterwidth;
4301 textureheight = waterheight;
4305 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4306 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4309 // allocate textures as needed
4310 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4312 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4313 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4315 if (p->texture_refraction)
4316 R_FreeTexture(p->texture_refraction);
4317 p->texture_refraction = NULL;
4318 if (p->texture_reflection)
4319 R_FreeTexture(p->texture_reflection);
4320 p->texture_reflection = NULL;
4322 memset(&r_waterstate, 0, sizeof(r_waterstate));
4323 r_waterstate.texturewidth = texturewidth;
4324 r_waterstate.textureheight = textureheight;
4327 if (r_waterstate.texturewidth)
4329 r_waterstate.enabled = true;
4331 // when doing a reduced render (HDR) we want to use a smaller area
4332 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4333 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4335 // set up variables that will be used in shader setup
4336 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4337 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4338 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4339 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4342 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4343 r_waterstate.numwaterplanes = 0;
4346 void R_Water_AddWaterPlane(msurface_t *surface)
4348 int triangleindex, planeindex;
4354 r_waterstate_waterplane_t *p;
4355 texture_t *t = R_GetCurrentTexture(surface->texture);
4356 // just use the first triangle with a valid normal for any decisions
4357 VectorClear(normal);
4358 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4360 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4361 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4362 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4363 TriangleNormal(vert[0], vert[1], vert[2], normal);
4364 if (VectorLength2(normal) >= 0.001)
4368 VectorCopy(normal, plane.normal);
4369 VectorNormalize(plane.normal);
4370 plane.dist = DotProduct(vert[0], plane.normal);
4371 PlaneClassify(&plane);
4372 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4374 // skip backfaces (except if nocullface is set)
4375 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4377 VectorNegate(plane.normal, plane.normal);
4379 PlaneClassify(&plane);
4383 // find a matching plane if there is one
4384 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4385 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4387 if (planeindex >= r_waterstate.maxwaterplanes)
4388 return; // nothing we can do, out of planes
4390 // if this triangle does not fit any known plane rendered this frame, add one
4391 if (planeindex >= r_waterstate.numwaterplanes)
4393 // store the new plane
4394 r_waterstate.numwaterplanes++;
4396 // clear materialflags and pvs
4397 p->materialflags = 0;
4398 p->pvsvalid = false;
4400 // merge this surface's materialflags into the waterplane
4401 p->materialflags |= t->currentmaterialflags;
4402 // merge this surface's PVS into the waterplane
4403 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4404 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4405 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4407 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4412 static void R_Water_ProcessPlanes(void)
4414 r_refdef_view_t originalview;
4415 r_refdef_view_t myview;
4417 r_waterstate_waterplane_t *p;
4419 originalview = r_refdef.view;
4421 // make sure enough textures are allocated
4422 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4424 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4426 if (!p->texture_refraction)
4427 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);
4428 if (!p->texture_refraction)
4432 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4434 if (!p->texture_reflection)
4435 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);
4436 if (!p->texture_reflection)
4442 r_refdef.view = originalview;
4443 r_refdef.view.showdebug = false;
4444 r_refdef.view.width = r_waterstate.waterwidth;
4445 r_refdef.view.height = r_waterstate.waterheight;
4446 r_refdef.view.useclipplane = true;
4447 myview = r_refdef.view;
4448 r_waterstate.renderingscene = true;
4449 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4451 // render the normal view scene and copy into texture
4452 // (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)
4453 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4455 r_refdef.view = myview;
4456 r_refdef.view.clipplane = p->plane;
4457 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4458 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4459 PlaneClassify(&r_refdef.view.clipplane);
4461 R_ResetViewRendering3D();
4462 R_ClearScreen(r_refdef.fogenabled);
4466 // copy view into the screen texture
4467 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4468 GL_ActiveTexture(0);
4470 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
4473 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4475 r_refdef.view = myview;
4476 // render reflected scene and copy into texture
4477 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4478 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4479 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4480 r_refdef.view.clipplane = p->plane;
4481 // reverse the cullface settings for this render
4482 r_refdef.view.cullface_front = GL_FRONT;
4483 r_refdef.view.cullface_back = GL_BACK;
4484 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4486 r_refdef.view.usecustompvs = true;
4488 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4490 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4493 R_ResetViewRendering3D();
4494 R_ClearScreen(r_refdef.fogenabled);
4498 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4499 GL_ActiveTexture(0);
4501 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
4504 r_waterstate.renderingscene = false;
4505 r_refdef.view = originalview;
4506 R_ResetViewRendering3D();
4507 R_ClearScreen(r_refdef.fogenabled);
4511 r_refdef.view = originalview;
4512 r_waterstate.renderingscene = false;
4513 Cvar_SetValueQuick(&r_water, 0);
4514 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4518 void R_Bloom_StartFrame(void)
4520 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4522 switch(vid.renderpath)
4524 case RENDERPATH_GL20:
4526 case RENDERPATH_GL13:
4527 case RENDERPATH_GL11:
4531 // set bloomwidth and bloomheight to the bloom resolution that will be
4532 // used (often less than the screen resolution for faster rendering)
4533 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4534 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4535 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4536 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
4537 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
4539 // calculate desired texture sizes
4540 if (vid.support.arb_texture_non_power_of_two)
4542 screentexturewidth = r_refdef.view.width;
4543 screentextureheight = r_refdef.view.height;
4544 bloomtexturewidth = r_bloomstate.bloomwidth;
4545 bloomtextureheight = r_bloomstate.bloomheight;
4549 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4550 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4551 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4552 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4555 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
4557 Cvar_SetValueQuick(&r_hdr, 0);
4558 Cvar_SetValueQuick(&r_bloom, 0);
4559 Cvar_SetValueQuick(&r_motionblur, 0);
4560 Cvar_SetValueQuick(&r_damageblur, 0);
4563 if (!(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)))
4564 screentexturewidth = screentextureheight = 0;
4565 if (!r_hdr.integer && !r_bloom.integer)
4566 bloomtexturewidth = bloomtextureheight = 0;
4568 // allocate textures as needed
4569 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4571 if (r_bloomstate.texture_screen)
4572 R_FreeTexture(r_bloomstate.texture_screen);
4573 r_bloomstate.texture_screen = NULL;
4574 r_bloomstate.screentexturewidth = screentexturewidth;
4575 r_bloomstate.screentextureheight = screentextureheight;
4576 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4577 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);
4579 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4581 if (r_bloomstate.texture_bloom)
4582 R_FreeTexture(r_bloomstate.texture_bloom);
4583 r_bloomstate.texture_bloom = NULL;
4584 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4585 r_bloomstate.bloomtextureheight = bloomtextureheight;
4586 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4587 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);
4590 // when doing a reduced render (HDR) we want to use a smaller area
4591 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4592 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4593 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4594 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4595 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4597 // set up a texcoord array for the full resolution screen image
4598 // (we have to keep this around to copy back during final render)
4599 r_bloomstate.screentexcoord2f[0] = 0;
4600 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4601 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4602 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4603 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4604 r_bloomstate.screentexcoord2f[5] = 0;
4605 r_bloomstate.screentexcoord2f[6] = 0;
4606 r_bloomstate.screentexcoord2f[7] = 0;
4608 // set up a texcoord array for the reduced resolution bloom image
4609 // (which will be additive blended over the screen image)
4610 r_bloomstate.bloomtexcoord2f[0] = 0;
4611 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4612 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4613 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4614 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4615 r_bloomstate.bloomtexcoord2f[5] = 0;
4616 r_bloomstate.bloomtexcoord2f[6] = 0;
4617 r_bloomstate.bloomtexcoord2f[7] = 0;
4619 if (r_hdr.integer || r_bloom.integer)
4621 r_bloomstate.enabled = true;
4622 r_bloomstate.hdr = r_hdr.integer != 0;
4625 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);
4628 void R_Bloom_CopyBloomTexture(float colorscale)
4630 r_refdef.stats.bloom++;
4632 // scale down screen texture to the bloom texture size
4634 R_SetViewport(&r_bloomstate.viewport);
4635 GL_BlendFunc(GL_ONE, GL_ZERO);
4636 GL_Color(colorscale, colorscale, colorscale, 1);
4637 // TODO: optimize with multitexture or GLSL
4638 R_SetupGenericShader(true);
4639 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4640 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4641 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4642 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4644 // we now have a bloom image in the framebuffer
4645 // copy it into the bloom image texture for later processing
4646 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4647 GL_ActiveTexture(0);
4649 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4650 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4653 void R_Bloom_CopyHDRTexture(void)
4655 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4656 GL_ActiveTexture(0);
4658 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
4659 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4662 void R_Bloom_MakeTexture(void)
4665 float xoffset, yoffset, r, brighten;
4667 r_refdef.stats.bloom++;
4669 R_ResetViewRendering2D();
4670 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4671 R_Mesh_ColorPointer(NULL, 0, 0);
4672 R_SetupGenericShader(true);
4674 // we have a bloom image in the framebuffer
4676 R_SetViewport(&r_bloomstate.viewport);
4678 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4681 r = bound(0, r_bloom_colorexponent.value / x, 1);
4682 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4683 GL_Color(r, r, r, 1);
4684 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4685 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4686 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4687 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4689 // copy the vertically blurred bloom view to a texture
4690 GL_ActiveTexture(0);
4692 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4693 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4696 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4697 brighten = r_bloom_brighten.value;
4699 brighten *= r_hdr_range.value;
4700 brighten = sqrt(brighten);
4702 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4703 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4704 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4706 for (dir = 0;dir < 2;dir++)
4708 // blend on at multiple vertical offsets to achieve a vertical blur
4709 // TODO: do offset blends using GLSL
4710 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4711 GL_BlendFunc(GL_ONE, GL_ZERO);
4712 for (x = -range;x <= range;x++)
4714 if (!dir){xoffset = 0;yoffset = x;}
4715 else {xoffset = x;yoffset = 0;}
4716 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4717 yoffset /= (float)r_bloomstate.bloomtextureheight;
4718 // compute a texcoord array with the specified x and y offset
4719 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4720 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4721 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4722 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4723 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4724 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4725 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4726 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4727 // this r value looks like a 'dot' particle, fading sharply to
4728 // black at the edges
4729 // (probably not realistic but looks good enough)
4730 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4731 //r = brighten/(range*2+1);
4732 r = brighten / (range * 2 + 1);
4734 r *= (1 - x*x/(float)(range*range));
4735 GL_Color(r, r, r, 1);
4736 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4737 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4738 GL_BlendFunc(GL_ONE, GL_ONE);
4741 // copy the vertically blurred bloom view to a texture
4742 GL_ActiveTexture(0);
4744 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4745 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4748 // apply subtract last
4749 // (just like it would be in a GLSL shader)
4750 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
4752 GL_BlendFunc(GL_ONE, GL_ZERO);
4753 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4754 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4755 GL_Color(1, 1, 1, 1);
4756 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4757 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4759 GL_BlendFunc(GL_ONE, GL_ONE);
4760 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4761 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4762 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4763 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4764 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4765 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4766 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4768 // copy the darkened bloom view to a texture
4769 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4770 GL_ActiveTexture(0);
4772 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4773 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4777 void R_HDR_RenderBloomTexture(void)
4779 int oldwidth, oldheight;
4780 float oldcolorscale;
4782 oldcolorscale = r_refdef.view.colorscale;
4783 oldwidth = r_refdef.view.width;
4784 oldheight = r_refdef.view.height;
4785 r_refdef.view.width = r_bloomstate.bloomwidth;
4786 r_refdef.view.height = r_bloomstate.bloomheight;
4788 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4789 // TODO: add exposure compensation features
4790 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4792 r_refdef.view.showdebug = false;
4793 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4795 R_ResetViewRendering3D();
4797 R_ClearScreen(r_refdef.fogenabled);
4798 if (r_timereport_active)
4799 R_TimeReport("HDRclear");
4802 if (r_timereport_active)
4803 R_TimeReport("visibility");
4805 // only do secondary renders with HDR if r_hdr is 2 or higher
4806 r_waterstate.numwaterplanes = 0;
4807 if (r_waterstate.enabled && r_hdr.integer >= 2)
4808 R_RenderWaterPlanes();
4810 r_refdef.view.showdebug = true;
4812 r_waterstate.numwaterplanes = 0;
4814 R_ResetViewRendering2D();
4816 R_Bloom_CopyHDRTexture();
4817 R_Bloom_MakeTexture();
4819 // restore the view settings
4820 r_refdef.view.width = oldwidth;
4821 r_refdef.view.height = oldheight;
4822 r_refdef.view.colorscale = oldcolorscale;
4824 R_ResetViewRendering3D();
4826 R_ClearScreen(r_refdef.fogenabled);
4827 if (r_timereport_active)
4828 R_TimeReport("viewclear");
4831 static void R_BlendView(void)
4833 unsigned int permutation;
4835 switch (vid.renderpath)
4837 case RENDERPATH_GL20:
4839 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4840 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4841 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4842 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4843 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4845 if (r_bloomstate.texture_screen)
4847 // make sure the buffer is available
4848 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4850 R_ResetViewRendering2D();
4851 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4852 R_Mesh_ColorPointer(NULL, 0, 0);
4853 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4854 GL_ActiveTexture(0);CHECKGLERROR
4856 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4858 // declare variables
4860 static float avgspeed;
4862 speed = VectorLength(cl.movement_velocity);
4864 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4865 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4867 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4868 speed = bound(0, speed, 1);
4869 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4871 // calculate values into a standard alpha
4872 cl.motionbluralpha = 1 - exp(-
4874 (r_motionblur.value * speed / 80)
4876 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4879 max(0.0001, cl.time - cl.oldtime) // fps independent
4882 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4883 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4885 if (cl.motionbluralpha > 0)
4887 R_SetupGenericShader(true);
4888 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4889 GL_Color(1, 1, 1, cl.motionbluralpha);
4890 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4891 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4892 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4893 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4897 // copy view into the screen texture
4898 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
4899 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4901 else if (!r_bloomstate.texture_bloom)
4903 // we may still have to do view tint...
4904 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4906 // apply a color tint to the whole view
4907 R_ResetViewRendering2D();
4908 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4909 R_Mesh_ColorPointer(NULL, 0, 0);
4910 R_SetupGenericShader(false);
4911 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4912 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4913 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4915 break; // no screen processing, no bloom, skip it
4918 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4920 // render simple bloom effect
4921 // copy the screen and shrink it and darken it for the bloom process
4922 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4923 // make the bloom texture
4924 R_Bloom_MakeTexture();
4927 R_ResetViewRendering2D();
4928 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4929 R_Mesh_ColorPointer(NULL, 0, 0);
4930 GL_Color(1, 1, 1, 1);
4931 GL_BlendFunc(GL_ONE, GL_ZERO);
4932 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4933 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4934 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4935 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4936 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4937 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4938 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4939 if (r_glsl_permutation->loc_ViewTintColor >= 0)
4940 qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4941 if (r_glsl_permutation->loc_ClientTime >= 0)
4942 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4943 if (r_glsl_permutation->loc_PixelSize >= 0)
4944 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4945 if (r_glsl_permutation->loc_UserVec1 >= 0)
4947 float a=0, b=0, c=0, d=0;
4948 #if _MSC_VER >= 1400
4949 #define sscanf sscanf_s
4951 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4952 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4954 if (r_glsl_permutation->loc_UserVec2 >= 0)
4956 float a=0, b=0, c=0, d=0;
4957 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4958 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4960 if (r_glsl_permutation->loc_UserVec3 >= 0)
4962 float a=0, b=0, c=0, d=0;
4963 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4964 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4966 if (r_glsl_permutation->loc_UserVec4 >= 0)
4968 float a=0, b=0, c=0, d=0;
4969 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4970 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4972 if (r_glsl_permutation->loc_Saturation >= 0)
4973 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4974 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4975 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4977 case RENDERPATH_GL13:
4978 case RENDERPATH_GL11:
4979 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4981 // apply a color tint to the whole view
4982 R_ResetViewRendering2D();
4983 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4984 R_Mesh_ColorPointer(NULL, 0, 0);
4985 R_SetupGenericShader(false);
4986 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4987 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4988 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4994 matrix4x4_t r_waterscrollmatrix;
4996 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4998 if (r_refdef.fog_density)
5000 r_refdef.fogcolor[0] = r_refdef.fog_red;
5001 r_refdef.fogcolor[1] = r_refdef.fog_green;
5002 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5004 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5005 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5006 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5007 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5011 VectorCopy(r_refdef.fogcolor, fogvec);
5012 // color.rgb *= ContrastBoost * SceneBrightness;
5013 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5014 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5015 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5016 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5021 void R_UpdateVariables(void)
5025 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
5027 r_refdef.farclip = r_farclip_base.value;
5028 if (r_refdef.scene.worldmodel)
5029 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5030 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5032 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5033 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5034 r_refdef.polygonfactor = 0;
5035 r_refdef.polygonoffset = 0;
5036 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5037 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5039 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5040 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5041 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
5042 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5043 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5044 if (r_showsurfaces.integer)
5046 r_refdef.scene.rtworld = false;
5047 r_refdef.scene.rtworldshadows = false;
5048 r_refdef.scene.rtdlight = false;
5049 r_refdef.scene.rtdlightshadows = false;
5050 r_refdef.lightmapintensity = 0;
5053 if (gamemode == GAME_NEHAHRA)
5055 if (gl_fogenable.integer)
5057 r_refdef.oldgl_fogenable = true;
5058 r_refdef.fog_density = gl_fogdensity.value;
5059 r_refdef.fog_red = gl_fogred.value;
5060 r_refdef.fog_green = gl_foggreen.value;
5061 r_refdef.fog_blue = gl_fogblue.value;
5062 r_refdef.fog_alpha = 1;
5063 r_refdef.fog_start = 0;
5064 r_refdef.fog_end = gl_skyclip.value;
5065 r_refdef.fog_height = 1<<30;
5066 r_refdef.fog_fadedepth = 128;
5068 else if (r_refdef.oldgl_fogenable)
5070 r_refdef.oldgl_fogenable = false;
5071 r_refdef.fog_density = 0;
5072 r_refdef.fog_red = 0;
5073 r_refdef.fog_green = 0;
5074 r_refdef.fog_blue = 0;
5075 r_refdef.fog_alpha = 0;
5076 r_refdef.fog_start = 0;
5077 r_refdef.fog_end = 0;
5078 r_refdef.fog_height = 1<<30;
5079 r_refdef.fog_fadedepth = 128;
5083 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5084 r_refdef.fog_start = max(0, r_refdef.fog_start);
5085 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5087 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
5089 if (r_refdef.fog_density && r_drawfog.integer)
5091 r_refdef.fogenabled = true;
5092 // this is the point where the fog reaches 0.9986 alpha, which we
5093 // consider a good enough cutoff point for the texture
5094 // (0.9986 * 256 == 255.6)
5095 if (r_fog_exp2.integer)
5096 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5098 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5099 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5100 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5101 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5102 // fog color was already set
5103 // update the fog texture
5104 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)
5105 R_BuildFogTexture();
5108 r_refdef.fogenabled = false;
5110 switch(vid.renderpath)
5112 case RENDERPATH_GL20:
5113 if(v_glslgamma.integer && !vid_gammatables_trivial)
5115 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5117 // build GLSL gamma texture
5118 #define RAMPWIDTH 256
5119 unsigned short ramp[RAMPWIDTH * 3];
5120 unsigned char rampbgr[RAMPWIDTH][4];
5123 r_texture_gammaramps_serial = vid_gammatables_serial;
5125 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5126 for(i = 0; i < RAMPWIDTH; ++i)
5128 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5129 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5130 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5133 if (r_texture_gammaramps)
5135 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
5139 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
5145 // remove GLSL gamma texture
5148 case RENDERPATH_GL13:
5149 case RENDERPATH_GL11:
5154 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5155 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5161 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5162 if( scenetype != r_currentscenetype ) {
5163 // store the old scenetype
5164 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5165 r_currentscenetype = scenetype;
5166 // move in the new scene
5167 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5176 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5178 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5179 if( scenetype == r_currentscenetype ) {
5180 return &r_refdef.scene;
5182 return &r_scenes_store[ scenetype ];
5191 void R_RenderView(void)
5193 if (r_timereport_active)
5194 R_TimeReport("start");
5195 r_frame++; // used only by R_GetCurrentTexture
5196 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5198 if (!r_drawentities.integer)
5199 r_refdef.scene.numentities = 0;
5201 R_AnimCache_ClearCache();
5202 R_FrameData_NewFrame();
5204 if (r_refdef.view.isoverlay)
5206 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5207 GL_Clear( GL_DEPTH_BUFFER_BIT );
5208 R_TimeReport("depthclear");
5210 r_refdef.view.showdebug = false;
5212 r_waterstate.enabled = false;
5213 r_waterstate.numwaterplanes = 0;
5221 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
5222 return; //Host_Error ("R_RenderView: NULL worldmodel");
5224 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
5226 // break apart the view matrix into vectors for various purposes
5227 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5228 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5229 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5230 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5231 // make an inverted copy of the view matrix for tracking sprites
5232 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5234 R_Shadow_UpdateWorldLightSelection();
5236 R_Bloom_StartFrame();
5237 R_Water_StartFrame();
5240 if (r_timereport_active)
5241 R_TimeReport("viewsetup");
5243 R_ResetViewRendering3D();
5245 if (r_refdef.view.clear || r_refdef.fogenabled)
5247 R_ClearScreen(r_refdef.fogenabled);
5248 if (r_timereport_active)
5249 R_TimeReport("viewclear");
5251 r_refdef.view.clear = true;
5253 // this produces a bloom texture to be used in R_BlendView() later
5254 if (r_hdr.integer && r_bloomstate.bloomwidth)
5255 R_HDR_RenderBloomTexture();
5257 r_refdef.view.showdebug = true;
5260 if (r_timereport_active)
5261 R_TimeReport("visibility");
5263 r_waterstate.numwaterplanes = 0;
5264 if (r_waterstate.enabled)
5265 R_RenderWaterPlanes();
5268 r_waterstate.numwaterplanes = 0;
5271 if (r_timereport_active)
5272 R_TimeReport("blendview");
5274 GL_Scissor(0, 0, vid.width, vid.height);
5275 GL_ScissorTest(false);
5279 void R_RenderWaterPlanes(void)
5281 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5283 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5284 if (r_timereport_active)
5285 R_TimeReport("waterworld");
5288 // don't let sound skip if going slow
5289 if (r_refdef.scene.extraupdate)
5292 R_DrawModelsAddWaterPlanes();
5293 if (r_timereport_active)
5294 R_TimeReport("watermodels");
5296 if (r_waterstate.numwaterplanes)
5298 R_Water_ProcessPlanes();
5299 if (r_timereport_active)
5300 R_TimeReport("waterscenes");
5304 extern void R_DrawLightningBeams (void);
5305 extern void VM_CL_AddPolygonsToMeshQueue (void);
5306 extern void R_DrawPortals (void);
5307 extern cvar_t cl_locs_show;
5308 static void R_DrawLocs(void);
5309 static void R_DrawEntityBBoxes(void);
5310 static void R_DrawModelDecals(void);
5311 extern cvar_t cl_decals_newsystem;
5312 extern qboolean r_shadow_usingdeferredprepass;
5313 void R_RenderScene(void)
5315 r_refdef.stats.renders++;
5319 // don't let sound skip if going slow
5320 if (r_refdef.scene.extraupdate)
5323 R_MeshQueue_BeginScene();
5327 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);
5329 if (cl.csqc_vidvars.drawworld)
5331 // don't let sound skip if going slow
5332 if (r_refdef.scene.extraupdate)
5335 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5337 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5338 if (r_timereport_active)
5339 R_TimeReport("worldsky");
5342 if (R_DrawBrushModelsSky() && r_timereport_active)
5343 R_TimeReport("bmodelsky");
5345 if (skyrendermasked && skyrenderlater)
5347 // we have to force off the water clipping plane while rendering sky
5351 if (r_timereport_active)
5352 R_TimeReport("sky");
5356 R_AnimCache_CacheVisibleEntities();
5357 if (r_timereport_active)
5358 R_TimeReport("animation");
5360 R_Shadow_PrepareLights();
5361 if (r_timereport_active)
5362 R_TimeReport("preparelights");
5364 if (r_shadow_usingdeferredprepass)
5365 R_Shadow_DrawPrepass();
5367 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5369 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5370 if (r_timereport_active)
5371 R_TimeReport("worlddepth");
5373 if (r_depthfirst.integer >= 2)
5375 R_DrawModelsDepth();
5376 if (r_timereport_active)
5377 R_TimeReport("modeldepth");
5380 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5382 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5383 if (r_timereport_active)
5384 R_TimeReport("world");
5387 // don't let sound skip if going slow
5388 if (r_refdef.scene.extraupdate)
5392 if (r_timereport_active)
5393 R_TimeReport("models");
5395 // don't let sound skip if going slow
5396 if (r_refdef.scene.extraupdate)
5399 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5401 R_DrawModelShadows();
5402 R_ResetViewRendering3D();
5403 // don't let sound skip if going slow
5404 if (r_refdef.scene.extraupdate)
5408 if (!r_shadow_usingdeferredprepass)
5410 R_Shadow_DrawLights();
5411 if (r_timereport_active)
5412 R_TimeReport("rtlights");
5415 // don't let sound skip if going slow
5416 if (r_refdef.scene.extraupdate)
5419 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5421 R_DrawModelShadows();
5422 R_ResetViewRendering3D();
5423 // don't let sound skip if going slow
5424 if (r_refdef.scene.extraupdate)
5428 if (cl.csqc_vidvars.drawworld)
5430 if (cl_decals_newsystem.integer)
5432 R_DrawModelDecals();
5433 if (r_timereport_active)
5434 R_TimeReport("modeldecals");
5439 if (r_timereport_active)
5440 R_TimeReport("decals");
5444 if (r_timereport_active)
5445 R_TimeReport("particles");
5448 if (r_timereport_active)
5449 R_TimeReport("explosions");
5451 R_DrawLightningBeams();
5452 if (r_timereport_active)
5453 R_TimeReport("lightning");
5456 R_SetupGenericShader(true);
5457 VM_CL_AddPolygonsToMeshQueue();
5459 if (r_refdef.view.showdebug)
5461 if (cl_locs_show.integer)
5464 if (r_timereport_active)
5465 R_TimeReport("showlocs");
5468 if (r_drawportals.integer)
5471 if (r_timereport_active)
5472 R_TimeReport("portals");
5475 if (r_showbboxes.value > 0)
5477 R_DrawEntityBBoxes();
5478 if (r_timereport_active)
5479 R_TimeReport("bboxes");
5483 R_SetupGenericShader(true);
5484 R_MeshQueue_RenderTransparent();
5485 if (r_timereport_active)
5486 R_TimeReport("drawtrans");
5488 R_SetupGenericShader(true);
5490 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))
5492 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5493 if (r_timereport_active)
5494 R_TimeReport("worlddebug");
5495 R_DrawModelsDebug();
5496 if (r_timereport_active)
5497 R_TimeReport("modeldebug");
5500 R_SetupGenericShader(true);
5502 if (cl.csqc_vidvars.drawworld)
5504 R_Shadow_DrawCoronas();
5505 if (r_timereport_active)
5506 R_TimeReport("coronas");
5509 // don't let sound skip if going slow
5510 if (r_refdef.scene.extraupdate)
5513 R_ResetViewRendering2D();
5516 static const unsigned short bboxelements[36] =
5526 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5529 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5531 RSurf_ActiveWorldEntity();
5533 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5534 GL_DepthMask(false);
5535 GL_DepthRange(0, 1);
5536 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5537 R_Mesh_ResetTextureState();
5539 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5540 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5541 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5542 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5543 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5544 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5545 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5546 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5547 R_FillColors(color4f, 8, cr, cg, cb, ca);
5548 if (r_refdef.fogenabled)
5550 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5552 f1 = RSurf_FogVertex(v);
5554 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5555 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5556 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5559 R_Mesh_VertexPointer(vertex3f, 0, 0);
5560 R_Mesh_ColorPointer(color4f, 0, 0);
5561 R_Mesh_ResetTextureState();
5562 R_SetupGenericShader(false);
5563 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5566 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5570 prvm_edict_t *edict;
5571 prvm_prog_t *prog_save = prog;
5573 // this function draws bounding boxes of server entities
5577 GL_CullFace(GL_NONE);
5578 R_SetupGenericShader(false);
5582 for (i = 0;i < numsurfaces;i++)
5584 edict = PRVM_EDICT_NUM(surfacelist[i]);
5585 switch ((int)edict->fields.server->solid)
5587 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5588 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5589 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5590 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5591 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5592 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5594 color[3] *= r_showbboxes.value;
5595 color[3] = bound(0, color[3], 1);
5596 GL_DepthTest(!r_showdisabledepthtest.integer);
5597 GL_CullFace(r_refdef.view.cullface_front);
5598 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5604 static void R_DrawEntityBBoxes(void)
5607 prvm_edict_t *edict;
5609 prvm_prog_t *prog_save = prog;
5611 // this function draws bounding boxes of server entities
5617 for (i = 0;i < prog->num_edicts;i++)
5619 edict = PRVM_EDICT_NUM(i);
5620 if (edict->priv.server->free)
5622 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5623 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5625 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5627 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5628 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5634 static const int nomodelelement3i[24] =
5646 static const unsigned short nomodelelement3s[24] =
5658 static const float nomodelvertex3f[6*3] =
5668 static const float nomodelcolor4f[6*4] =
5670 0.0f, 0.0f, 0.5f, 1.0f,
5671 0.0f, 0.0f, 0.5f, 1.0f,
5672 0.0f, 0.5f, 0.0f, 1.0f,
5673 0.0f, 0.5f, 0.0f, 1.0f,
5674 0.5f, 0.0f, 0.0f, 1.0f,
5675 0.5f, 0.0f, 0.0f, 1.0f
5678 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5684 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);
5686 // this is only called once per entity so numsurfaces is always 1, and
5687 // surfacelist is always {0}, so this code does not handle batches
5689 if (rsurface.ent_flags & RENDER_ADDITIVE)
5691 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5692 GL_DepthMask(false);
5694 else if (rsurface.colormod[3] < 1)
5696 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5697 GL_DepthMask(false);
5701 GL_BlendFunc(GL_ONE, GL_ZERO);
5704 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5705 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5706 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5707 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5708 R_SetupGenericShader(false);
5709 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5710 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5711 R_Mesh_ColorPointer(color4f, 0, 0);
5712 for (i = 0, c = color4f;i < 6;i++, c += 4)
5714 c[0] *= rsurface.colormod[0];
5715 c[1] *= rsurface.colormod[1];
5716 c[2] *= rsurface.colormod[2];
5717 c[3] *= rsurface.colormod[3];
5719 if (r_refdef.fogenabled)
5721 for (i = 0, c = color4f;i < 6;i++, c += 4)
5723 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5725 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5726 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5727 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5730 R_Mesh_ResetTextureState();
5731 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5734 void R_DrawNoModel(entity_render_t *ent)
5737 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5738 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5739 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5741 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5744 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5746 vec3_t right1, right2, diff, normal;
5748 VectorSubtract (org2, org1, normal);
5750 // calculate 'right' vector for start
5751 VectorSubtract (r_refdef.view.origin, org1, diff);
5752 CrossProduct (normal, diff, right1);
5753 VectorNormalize (right1);
5755 // calculate 'right' vector for end
5756 VectorSubtract (r_refdef.view.origin, org2, diff);
5757 CrossProduct (normal, diff, right2);
5758 VectorNormalize (right2);
5760 vert[ 0] = org1[0] + width * right1[0];
5761 vert[ 1] = org1[1] + width * right1[1];
5762 vert[ 2] = org1[2] + width * right1[2];
5763 vert[ 3] = org1[0] - width * right1[0];
5764 vert[ 4] = org1[1] - width * right1[1];
5765 vert[ 5] = org1[2] - width * right1[2];
5766 vert[ 6] = org2[0] - width * right2[0];
5767 vert[ 7] = org2[1] - width * right2[1];
5768 vert[ 8] = org2[2] - width * right2[2];
5769 vert[ 9] = org2[0] + width * right2[0];
5770 vert[10] = org2[1] + width * right2[1];
5771 vert[11] = org2[2] + width * right2[2];
5774 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)
5776 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5777 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5778 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5779 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5780 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5781 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5782 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5783 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5784 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5785 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5786 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5787 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5790 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5795 VectorSet(v, x, y, z);
5796 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5797 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5799 if (i == mesh->numvertices)
5801 if (mesh->numvertices < mesh->maxvertices)
5803 VectorCopy(v, vertex3f);
5804 mesh->numvertices++;
5806 return mesh->numvertices;
5812 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5816 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5817 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5818 e = mesh->element3i + mesh->numtriangles * 3;
5819 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5821 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5822 if (mesh->numtriangles < mesh->maxtriangles)
5827 mesh->numtriangles++;
5829 element[1] = element[2];
5833 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5837 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5838 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5839 e = mesh->element3i + mesh->numtriangles * 3;
5840 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5842 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5843 if (mesh->numtriangles < mesh->maxtriangles)
5848 mesh->numtriangles++;
5850 element[1] = element[2];
5854 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5855 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5857 int planenum, planenum2;
5860 mplane_t *plane, *plane2;
5862 double temppoints[2][256*3];
5863 // figure out how large a bounding box we need to properly compute this brush
5865 for (w = 0;w < numplanes;w++)
5866 maxdist = max(maxdist, fabs(planes[w].dist));
5867 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5868 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5869 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5873 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5874 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5876 if (planenum2 == planenum)
5878 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);
5881 if (tempnumpoints < 3)
5883 // generate elements forming a triangle fan for this polygon
5884 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5888 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)
5890 texturelayer_t *layer;
5891 layer = t->currentlayers + t->currentnumlayers++;
5893 layer->depthmask = depthmask;
5894 layer->blendfunc1 = blendfunc1;
5895 layer->blendfunc2 = blendfunc2;
5896 layer->texture = texture;
5897 layer->texmatrix = *matrix;
5898 layer->color[0] = r;
5899 layer->color[1] = g;
5900 layer->color[2] = b;
5901 layer->color[3] = a;
5904 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5907 index = parms[2] + r_refdef.scene.time * parms[3];
5908 index -= floor(index);
5912 case Q3WAVEFUNC_NONE:
5913 case Q3WAVEFUNC_NOISE:
5914 case Q3WAVEFUNC_COUNT:
5917 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5918 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5919 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5920 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5921 case Q3WAVEFUNC_TRIANGLE:
5923 f = index - floor(index);
5934 return (float)(parms[0] + parms[1] * f);
5937 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5942 matrix4x4_t matrix, temp;
5943 switch(tcmod->tcmod)
5947 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5948 matrix = r_waterscrollmatrix;
5950 matrix = identitymatrix;
5952 case Q3TCMOD_ENTITYTRANSLATE:
5953 // this is used in Q3 to allow the gamecode to control texcoord
5954 // scrolling on the entity, which is not supported in darkplaces yet.
5955 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5957 case Q3TCMOD_ROTATE:
5958 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5959 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5960 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5963 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5965 case Q3TCMOD_SCROLL:
5966 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5968 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5969 w = (int) tcmod->parms[0];
5970 h = (int) tcmod->parms[1];
5971 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5973 idx = (int) floor(f * w * h);
5974 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5976 case Q3TCMOD_STRETCH:
5977 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5978 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5980 case Q3TCMOD_TRANSFORM:
5981 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5982 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5983 VectorSet(tcmat + 6, 0 , 0 , 1);
5984 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5985 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5987 case Q3TCMOD_TURBULENT:
5988 // this is handled in the RSurf_PrepareVertices function
5989 matrix = identitymatrix;
5993 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5996 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5998 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5999 char name[MAX_QPATH];
6000 skinframe_t *skinframe;
6001 unsigned char pixels[296*194];
6002 strlcpy(cache->name, skinname, sizeof(cache->name));
6003 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6004 if (developer_loading.integer)
6005 Con_Printf("loading %s\n", name);
6006 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6007 if (!skinframe || !skinframe->base)
6010 fs_offset_t filesize;
6012 f = FS_LoadFile(name, tempmempool, true, &filesize);
6015 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
6016 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6020 cache->skinframe = skinframe;
6023 texture_t *R_GetCurrentTexture(texture_t *t)
6026 const entity_render_t *ent = rsurface.entity;
6027 dp_model_t *model = ent->model;
6028 q3shaderinfo_layer_tcmod_t *tcmod;
6030 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
6031 return t->currentframe;
6032 t->update_lastrenderframe = r_frame;
6033 t->update_lastrenderentity = (void *)ent;
6035 // switch to an alternate material if this is a q1bsp animated material
6037 texture_t *texture = t;
6038 int s = rsurface.ent_skinnum;
6039 if ((unsigned int)s >= (unsigned int)model->numskins)
6041 if (model->skinscenes)
6043 if (model->skinscenes[s].framecount > 1)
6044 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6046 s = model->skinscenes[s].firstframe;
6049 t = t + s * model->num_surfaces;
6052 // use an alternate animation if the entity's frame is not 0,
6053 // and only if the texture has an alternate animation
6054 if (rsurface.ent_alttextures && t->anim_total[1])
6055 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
6057 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
6059 texture->currentframe = t;
6062 // update currentskinframe to be a qw skin or animation frame
6063 if (rsurface.ent_qwskin >= 0)
6065 i = rsurface.ent_qwskin;
6066 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6068 r_qwskincache_size = cl.maxclients;
6070 Mem_Free(r_qwskincache);
6071 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6073 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6074 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6075 t->currentskinframe = r_qwskincache[i].skinframe;
6076 if (t->currentskinframe == NULL)
6077 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6079 else if (t->numskinframes >= 2)
6080 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6081 if (t->backgroundnumskinframes >= 2)
6082 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
6084 t->currentmaterialflags = t->basematerialflags;
6085 t->currentalpha = rsurface.colormod[3];
6086 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
6087 t->currentalpha *= r_wateralpha.value;
6088 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
6089 t->currentalpha *= t->r_water_wateralpha;
6090 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
6091 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
6092 if (!(rsurface.ent_flags & RENDER_LIGHT))
6093 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
6094 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6096 // pick a model lighting mode
6097 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
6098 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
6100 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6102 if (rsurface.ent_flags & RENDER_ADDITIVE)
6103 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6104 else if (t->currentalpha < 1)
6105 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6106 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6107 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6108 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6109 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6110 if (t->backgroundnumskinframes)
6111 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6112 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6114 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
6115 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6118 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
6119 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6120 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6122 // there is no tcmod
6123 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6125 t->currenttexmatrix = r_waterscrollmatrix;
6126 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6128 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6130 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6131 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6134 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6135 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6136 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6137 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6139 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
6140 if (t->currentskinframe->qpixels)
6141 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6142 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6143 t->glosstexture = r_texture_black;
6144 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
6145 t->backgroundglosstexture = r_texture_black;
6146 t->specularpower = r_shadow_glossexponent.value;
6147 // TODO: store reference values for these in the texture?
6148 t->specularscale = 0;
6149 if (r_shadow_gloss.integer > 0)
6151 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6153 if (r_shadow_glossintensity.value > 0)
6155 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6156 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6157 t->specularscale = r_shadow_glossintensity.value;
6160 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6162 t->glosstexture = r_texture_white;
6163 t->backgroundglosstexture = r_texture_white;
6164 t->specularscale = r_shadow_gloss2intensity.value;
6165 t->specularpower = r_shadow_gloss2exponent.value;
6168 t->specularscale *= t->specularscalemod;
6169 t->specularpower *= t->specularpowermod;
6171 // lightmaps mode looks bad with dlights using actual texturing, so turn
6172 // off the colormap and glossmap, but leave the normalmap on as it still
6173 // accurately represents the shading involved
6174 if (gl_lightmaps.integer)
6176 t->basetexture = r_texture_grey128;
6177 t->backgroundbasetexture = NULL;
6178 t->specularscale = 0;
6179 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6182 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
6183 VectorClear(t->dlightcolor);
6184 t->currentnumlayers = 0;
6185 if (t->currentmaterialflags & MATERIALFLAG_WALL)
6187 int blendfunc1, blendfunc2;
6189 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6191 blendfunc1 = GL_SRC_ALPHA;
6192 blendfunc2 = GL_ONE;
6194 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6196 blendfunc1 = GL_SRC_ALPHA;
6197 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6199 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6201 blendfunc1 = t->customblendfunc[0];
6202 blendfunc2 = t->customblendfunc[1];
6206 blendfunc1 = GL_ONE;
6207 blendfunc2 = GL_ZERO;
6209 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
6210 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6212 // fullbright is not affected by r_refdef.lightmapintensity
6213 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]);
6214 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6215 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]);
6216 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6217 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]);
6221 vec3_t ambientcolor;
6223 // set the color tint used for lights affecting this surface
6224 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
6226 // q3bsp has no lightmap updates, so the lightstylevalue that
6227 // would normally be baked into the lightmap must be
6228 // applied to the color
6229 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
6230 if (model->type == mod_brushq3)
6231 colorscale *= r_refdef.scene.rtlightstylevalue[0];
6232 colorscale *= r_refdef.lightmapintensity;
6233 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
6234 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
6235 // basic lit geometry
6236 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]);
6237 // add pants/shirt if needed
6238 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6239 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]);
6240 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6241 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]);
6242 // now add ambient passes if needed
6243 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
6245 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]);
6246 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6247 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]);
6248 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6249 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]);
6252 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
6253 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
6254 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
6256 // if this is opaque use alpha blend which will darken the earlier
6259 // if this is an alpha blended material, all the earlier passes
6260 // were darkened by fog already, so we only need to add the fog
6261 // color ontop through the fog mask texture
6263 // if this is an additive blended material, all the earlier passes
6264 // were darkened by fog already, and we should not add fog color
6265 // (because the background was not darkened, there is no fog color
6266 // that was lost behind it).
6267 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &t->currenttexmatrix, 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]);
6271 return t->currentframe;
6274 rsurfacestate_t rsurface;
6276 void R_Mesh_ResizeArrays(int newvertices)
6279 if (rsurface.array_size >= newvertices)
6281 if (rsurface.array_modelvertex3f)
6282 Mem_Free(rsurface.array_modelvertex3f);
6283 rsurface.array_size = (newvertices + 1023) & ~1023;
6284 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
6285 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
6286 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
6287 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
6288 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
6289 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
6290 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
6291 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
6292 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
6293 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
6294 rsurface.array_color4f = base + rsurface.array_size * 27;
6295 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6298 void RSurf_ActiveWorldEntity(void)
6300 dp_model_t *model = r_refdef.scene.worldmodel;
6301 //if (rsurface.entity == r_refdef.scene.worldentity)
6303 rsurface.entity = r_refdef.scene.worldentity;
6304 rsurface.skeleton = NULL;
6305 rsurface.ent_skinnum = 0;
6306 rsurface.ent_qwskin = -1;
6307 rsurface.ent_shadertime = 0;
6308 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6309 if (rsurface.array_size < model->surfmesh.num_vertices)
6310 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6311 rsurface.matrix = identitymatrix;
6312 rsurface.inversematrix = identitymatrix;
6313 rsurface.matrixscale = 1;
6314 rsurface.inversematrixscale = 1;
6315 R_Mesh_Matrix(&identitymatrix);
6316 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6317 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6318 rsurface.fograngerecip = r_refdef.fograngerecip;
6319 rsurface.fogheightfade = r_refdef.fogheightfade;
6320 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6321 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6322 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6323 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6324 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6325 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6326 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6327 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
6328 rsurface.colormod[3] = 1;
6329 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
6330 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6331 rsurface.frameblend[0].lerp = 1;
6332 rsurface.ent_alttextures = false;
6333 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6334 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6335 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6336 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6337 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6338 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6339 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6340 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6341 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6342 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6343 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6344 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6345 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6346 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6347 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6348 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6349 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6350 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6351 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6352 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6353 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6354 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6355 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6356 rsurface.modelelement3i = model->surfmesh.data_element3i;
6357 rsurface.modelelement3s = model->surfmesh.data_element3s;
6358 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6359 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6360 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6361 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6362 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6363 rsurface.modelsurfaces = model->data_surfaces;
6364 rsurface.generatedvertex = false;
6365 rsurface.vertex3f = rsurface.modelvertex3f;
6366 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6367 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6368 rsurface.svector3f = rsurface.modelsvector3f;
6369 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6370 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6371 rsurface.tvector3f = rsurface.modeltvector3f;
6372 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6373 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6374 rsurface.normal3f = rsurface.modelnormal3f;
6375 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6376 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6377 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6380 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
6382 dp_model_t *model = ent->model;
6383 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6385 rsurface.entity = (entity_render_t *)ent;
6386 rsurface.skeleton = ent->skeleton;
6387 rsurface.ent_skinnum = ent->skinnum;
6388 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;
6389 rsurface.ent_shadertime = ent->shadertime;
6390 rsurface.ent_flags = ent->flags;
6391 if (rsurface.array_size < model->surfmesh.num_vertices)
6392 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6393 rsurface.matrix = ent->matrix;
6394 rsurface.inversematrix = ent->inversematrix;
6395 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6396 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6397 R_Mesh_Matrix(&rsurface.matrix);
6398 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6399 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6400 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6401 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6402 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6403 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6404 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6405 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6406 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6407 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6408 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6409 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
6410 rsurface.colormod[3] = ent->alpha;
6411 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
6412 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6413 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6414 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6415 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6416 if (ent->model->brush.submodel && !prepass)
6418 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6419 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6421 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6423 if (ent->animcache_vertex3f && !r_framedata_failed)
6425 rsurface.modelvertex3f = ent->animcache_vertex3f;
6426 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
6427 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
6428 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
6430 else if (wanttangents)
6432 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6433 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6434 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6435 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6436 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6438 else if (wantnormals)
6440 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6441 rsurface.modelsvector3f = NULL;
6442 rsurface.modeltvector3f = NULL;
6443 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6444 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6448 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6449 rsurface.modelsvector3f = NULL;
6450 rsurface.modeltvector3f = NULL;
6451 rsurface.modelnormal3f = NULL;
6452 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6454 rsurface.modelvertex3f_bufferobject = 0;
6455 rsurface.modelvertex3f_bufferoffset = 0;
6456 rsurface.modelsvector3f_bufferobject = 0;
6457 rsurface.modelsvector3f_bufferoffset = 0;
6458 rsurface.modeltvector3f_bufferobject = 0;
6459 rsurface.modeltvector3f_bufferoffset = 0;
6460 rsurface.modelnormal3f_bufferobject = 0;
6461 rsurface.modelnormal3f_bufferoffset = 0;
6462 rsurface.generatedvertex = true;
6466 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6467 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6468 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6469 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6470 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6471 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6472 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6473 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6474 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6475 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6476 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6477 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6478 rsurface.generatedvertex = false;
6480 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6481 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6482 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6483 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6484 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6485 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6486 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6487 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6488 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6489 rsurface.modelelement3i = model->surfmesh.data_element3i;
6490 rsurface.modelelement3s = model->surfmesh.data_element3s;
6491 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6492 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6493 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6494 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6495 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6496 rsurface.modelsurfaces = model->data_surfaces;
6497 rsurface.vertex3f = rsurface.modelvertex3f;
6498 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6499 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6500 rsurface.svector3f = rsurface.modelsvector3f;
6501 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6502 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6503 rsurface.tvector3f = rsurface.modeltvector3f;
6504 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6505 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6506 rsurface.normal3f = rsurface.modelnormal3f;
6507 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6508 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6509 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6512 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)
6514 rsurface.entity = r_refdef.scene.worldentity;
6515 rsurface.skeleton = NULL;
6516 rsurface.ent_skinnum = 0;
6517 rsurface.ent_qwskin = -1;
6518 rsurface.ent_shadertime = shadertime;
6519 rsurface.ent_flags = entflags;
6520 rsurface.modelnum_vertices = numvertices;
6521 rsurface.modelnum_triangles = numtriangles;
6522 if (rsurface.array_size < rsurface.modelnum_vertices)
6523 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6524 rsurface.matrix = *matrix;
6525 rsurface.inversematrix = *inversematrix;
6526 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6527 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6528 R_Mesh_Matrix(&rsurface.matrix);
6529 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6530 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6531 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6532 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6533 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6534 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6535 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6536 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6537 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6538 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6539 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6540 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
6541 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
6542 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6543 rsurface.frameblend[0].lerp = 1;
6544 rsurface.ent_alttextures = false;
6545 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6546 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6549 rsurface.modelvertex3f = vertex3f;
6550 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6551 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6552 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6554 else if (wantnormals)
6556 rsurface.modelvertex3f = vertex3f;
6557 rsurface.modelsvector3f = NULL;
6558 rsurface.modeltvector3f = NULL;
6559 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6563 rsurface.modelvertex3f = vertex3f;
6564 rsurface.modelsvector3f = NULL;
6565 rsurface.modeltvector3f = NULL;
6566 rsurface.modelnormal3f = NULL;
6568 rsurface.modelvertex3f_bufferobject = 0;
6569 rsurface.modelvertex3f_bufferoffset = 0;
6570 rsurface.modelsvector3f_bufferobject = 0;
6571 rsurface.modelsvector3f_bufferoffset = 0;
6572 rsurface.modeltvector3f_bufferobject = 0;
6573 rsurface.modeltvector3f_bufferoffset = 0;
6574 rsurface.modelnormal3f_bufferobject = 0;
6575 rsurface.modelnormal3f_bufferoffset = 0;
6576 rsurface.generatedvertex = true;
6577 rsurface.modellightmapcolor4f = color4f;
6578 rsurface.modellightmapcolor4f_bufferobject = 0;
6579 rsurface.modellightmapcolor4f_bufferoffset = 0;
6580 rsurface.modeltexcoordtexture2f = texcoord2f;
6581 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6582 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6583 rsurface.modeltexcoordlightmap2f = NULL;
6584 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6585 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6586 rsurface.modelelement3i = element3i;
6587 rsurface.modelelement3s = element3s;
6588 rsurface.modelelement3i_bufferobject = 0;
6589 rsurface.modelelement3s_bufferobject = 0;
6590 rsurface.modellightmapoffsets = NULL;
6591 rsurface.modelsurfaces = NULL;
6592 rsurface.vertex3f = rsurface.modelvertex3f;
6593 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6594 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6595 rsurface.svector3f = rsurface.modelsvector3f;
6596 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6597 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6598 rsurface.tvector3f = rsurface.modeltvector3f;
6599 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6600 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6601 rsurface.normal3f = rsurface.modelnormal3f;
6602 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6603 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6604 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6606 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6608 if ((wantnormals || wanttangents) && !normal3f)
6609 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6610 if (wanttangents && !svector3f)
6611 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);
6615 float RSurf_FogPoint(const float *v)
6617 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6618 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6619 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6620 float FogHeightFade = r_refdef.fogheightfade;
6622 unsigned int fogmasktableindex;
6623 if (r_refdef.fogplaneviewabove)
6624 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6626 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6627 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6628 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6631 float RSurf_FogVertex(const float *v)
6633 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6634 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6635 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6636 float FogHeightFade = rsurface.fogheightfade;
6638 unsigned int fogmasktableindex;
6639 if (r_refdef.fogplaneviewabove)
6640 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6642 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6643 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6644 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6647 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6648 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6651 int texturesurfaceindex;
6656 const float *v1, *in_tc;
6658 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6660 q3shaderinfo_deform_t *deform;
6661 // 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
6662 if (rsurface.generatedvertex)
6664 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6665 generatenormals = true;
6666 for (i = 0;i < Q3MAXDEFORMS;i++)
6668 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6670 generatetangents = true;
6671 generatenormals = true;
6673 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6674 generatenormals = true;
6676 if (generatenormals && !rsurface.modelnormal3f)
6678 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6679 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6680 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6681 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6683 if (generatetangents && !rsurface.modelsvector3f)
6685 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6686 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6687 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6688 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6689 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6690 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6691 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);
6694 rsurface.vertex3f = rsurface.modelvertex3f;
6695 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6696 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6697 rsurface.svector3f = rsurface.modelsvector3f;
6698 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6699 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6700 rsurface.tvector3f = rsurface.modeltvector3f;
6701 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6702 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6703 rsurface.normal3f = rsurface.modelnormal3f;
6704 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6705 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6706 // if vertices are deformed (sprite flares and things in maps, possibly
6707 // water waves, bulges and other deformations), generate them into
6708 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6709 // (may be static model data or generated data for an animated model, or
6710 // the previous deform pass)
6711 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6713 switch (deform->deform)
6716 case Q3DEFORM_PROJECTIONSHADOW:
6717 case Q3DEFORM_TEXT0:
6718 case Q3DEFORM_TEXT1:
6719 case Q3DEFORM_TEXT2:
6720 case Q3DEFORM_TEXT3:
6721 case Q3DEFORM_TEXT4:
6722 case Q3DEFORM_TEXT5:
6723 case Q3DEFORM_TEXT6:
6724 case Q3DEFORM_TEXT7:
6727 case Q3DEFORM_AUTOSPRITE:
6728 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6729 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6730 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6731 VectorNormalize(newforward);
6732 VectorNormalize(newright);
6733 VectorNormalize(newup);
6734 // make deformed versions of only the model vertices used by the specified surfaces
6735 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6737 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6738 // a single autosprite surface can contain multiple sprites...
6739 for (j = 0;j < surface->num_vertices - 3;j += 4)
6741 VectorClear(center);
6742 for (i = 0;i < 4;i++)
6743 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6744 VectorScale(center, 0.25f, center);
6745 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6746 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6747 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6748 for (i = 0;i < 4;i++)
6750 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6751 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6754 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);
6755 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);
6757 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6758 rsurface.vertex3f_bufferobject = 0;
6759 rsurface.vertex3f_bufferoffset = 0;
6760 rsurface.svector3f = rsurface.array_deformedsvector3f;
6761 rsurface.svector3f_bufferobject = 0;
6762 rsurface.svector3f_bufferoffset = 0;
6763 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6764 rsurface.tvector3f_bufferobject = 0;
6765 rsurface.tvector3f_bufferoffset = 0;
6766 rsurface.normal3f = rsurface.array_deformednormal3f;
6767 rsurface.normal3f_bufferobject = 0;
6768 rsurface.normal3f_bufferoffset = 0;
6770 case Q3DEFORM_AUTOSPRITE2:
6771 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6772 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6773 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6774 VectorNormalize(newforward);
6775 VectorNormalize(newright);
6776 VectorNormalize(newup);
6777 // make deformed versions of only the model vertices used by the specified surfaces
6778 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6780 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6781 const float *v1, *v2;
6791 memset(shortest, 0, sizeof(shortest));
6792 // a single autosprite surface can contain multiple sprites...
6793 for (j = 0;j < surface->num_vertices - 3;j += 4)
6795 VectorClear(center);
6796 for (i = 0;i < 4;i++)
6797 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6798 VectorScale(center, 0.25f, center);
6799 // find the two shortest edges, then use them to define the
6800 // axis vectors for rotating around the central axis
6801 for (i = 0;i < 6;i++)
6803 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6804 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6806 Debug_PolygonBegin(NULL, 0);
6807 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6808 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);
6809 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6812 l = VectorDistance2(v1, v2);
6813 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6815 l += (1.0f / 1024.0f);
6816 if (shortest[0].length2 > l || i == 0)
6818 shortest[1] = shortest[0];
6819 shortest[0].length2 = l;
6820 shortest[0].v1 = v1;
6821 shortest[0].v2 = v2;
6823 else if (shortest[1].length2 > l || i == 1)
6825 shortest[1].length2 = l;
6826 shortest[1].v1 = v1;
6827 shortest[1].v2 = v2;
6830 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6831 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6833 Debug_PolygonBegin(NULL, 0);
6834 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6835 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);
6836 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6839 // this calculates the right vector from the shortest edge
6840 // and the up vector from the edge midpoints
6841 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6842 VectorNormalize(right);
6843 VectorSubtract(end, start, up);
6844 VectorNormalize(up);
6845 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6846 VectorSubtract(rsurface.localvieworigin, center, forward);
6847 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6848 VectorNegate(forward, forward);
6849 VectorReflect(forward, 0, up, forward);
6850 VectorNormalize(forward);
6851 CrossProduct(up, forward, newright);
6852 VectorNormalize(newright);
6854 Debug_PolygonBegin(NULL, 0);
6855 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);
6856 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6857 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6861 Debug_PolygonBegin(NULL, 0);
6862 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6863 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6864 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6867 // rotate the quad around the up axis vector, this is made
6868 // especially easy by the fact we know the quad is flat,
6869 // so we only have to subtract the center position and
6870 // measure distance along the right vector, and then
6871 // multiply that by the newright vector and add back the
6873 // we also need to subtract the old position to undo the
6874 // displacement from the center, which we do with a
6875 // DotProduct, the subtraction/addition of center is also
6876 // optimized into DotProducts here
6877 l = DotProduct(right, center);
6878 for (i = 0;i < 4;i++)
6880 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6881 f = DotProduct(right, v1) - l;
6882 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6885 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);
6886 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);
6888 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6889 rsurface.vertex3f_bufferobject = 0;
6890 rsurface.vertex3f_bufferoffset = 0;
6891 rsurface.svector3f = rsurface.array_deformedsvector3f;
6892 rsurface.svector3f_bufferobject = 0;
6893 rsurface.svector3f_bufferoffset = 0;
6894 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6895 rsurface.tvector3f_bufferobject = 0;
6896 rsurface.tvector3f_bufferoffset = 0;
6897 rsurface.normal3f = rsurface.array_deformednormal3f;
6898 rsurface.normal3f_bufferobject = 0;
6899 rsurface.normal3f_bufferoffset = 0;
6901 case Q3DEFORM_NORMAL:
6902 // deform the normals to make reflections wavey
6903 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6905 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6906 for (j = 0;j < surface->num_vertices;j++)
6909 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6910 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6911 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6912 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6913 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6914 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6915 VectorNormalize(normal);
6917 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);
6919 rsurface.svector3f = rsurface.array_deformedsvector3f;
6920 rsurface.svector3f_bufferobject = 0;
6921 rsurface.svector3f_bufferoffset = 0;
6922 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6923 rsurface.tvector3f_bufferobject = 0;
6924 rsurface.tvector3f_bufferoffset = 0;
6925 rsurface.normal3f = rsurface.array_deformednormal3f;
6926 rsurface.normal3f_bufferobject = 0;
6927 rsurface.normal3f_bufferoffset = 0;
6930 // deform vertex array to make wavey water and flags and such
6931 waveparms[0] = deform->waveparms[0];
6932 waveparms[1] = deform->waveparms[1];
6933 waveparms[2] = deform->waveparms[2];
6934 waveparms[3] = deform->waveparms[3];
6935 // this is how a divisor of vertex influence on deformation
6936 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6937 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6938 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6940 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6941 for (j = 0;j < surface->num_vertices;j++)
6943 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6944 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6945 // if the wavefunc depends on time, evaluate it per-vertex
6948 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6949 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6951 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6954 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6955 rsurface.vertex3f_bufferobject = 0;
6956 rsurface.vertex3f_bufferoffset = 0;
6958 case Q3DEFORM_BULGE:
6959 // deform vertex array to make the surface have moving bulges
6960 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6962 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6963 for (j = 0;j < surface->num_vertices;j++)
6965 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6966 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6969 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6970 rsurface.vertex3f_bufferobject = 0;
6971 rsurface.vertex3f_bufferoffset = 0;
6974 // deform vertex array
6975 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6976 VectorScale(deform->parms, scale, waveparms);
6977 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6979 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6980 for (j = 0;j < surface->num_vertices;j++)
6981 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6983 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6984 rsurface.vertex3f_bufferobject = 0;
6985 rsurface.vertex3f_bufferoffset = 0;
6989 // generate texcoords based on the chosen texcoord source
6990 switch(rsurface.texture->tcgen.tcgen)
6993 case Q3TCGEN_TEXTURE:
6994 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6995 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6996 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6998 case Q3TCGEN_LIGHTMAP:
6999 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
7000 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7001 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7003 case Q3TCGEN_VECTOR:
7004 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7006 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7007 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)
7009 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
7010 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
7013 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7014 rsurface.texcoordtexture2f_bufferobject = 0;
7015 rsurface.texcoordtexture2f_bufferoffset = 0;
7017 case Q3TCGEN_ENVIRONMENT:
7018 // make environment reflections using a spheremap
7019 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7021 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7022 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
7023 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
7024 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
7025 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
7027 // identical to Q3A's method, but executed in worldspace so
7028 // carried models can be shiny too
7030 float viewer[3], d, reflected[3], worldreflected[3];
7032 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
7033 // VectorNormalize(viewer);
7035 d = DotProduct(normal, viewer);
7037 reflected[0] = normal[0]*2*d - viewer[0];
7038 reflected[1] = normal[1]*2*d - viewer[1];
7039 reflected[2] = normal[2]*2*d - viewer[2];
7040 // note: this is proportinal to viewer, so we can normalize later
7042 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7043 VectorNormalize(worldreflected);
7045 // note: this sphere map only uses world x and z!
7046 // so positive and negative y will LOOK THE SAME.
7047 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7048 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7051 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7052 rsurface.texcoordtexture2f_bufferobject = 0;
7053 rsurface.texcoordtexture2f_bufferoffset = 0;
7056 // the only tcmod that needs software vertex processing is turbulent, so
7057 // check for it here and apply the changes if needed
7058 // and we only support that as the first one
7059 // (handling a mixture of turbulent and other tcmods would be problematic
7060 // without punting it entirely to a software path)
7061 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7063 amplitude = rsurface.texture->tcmods[0].parms[1];
7064 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7065 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7067 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7068 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)
7070 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7071 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7074 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7075 rsurface.texcoordtexture2f_bufferobject = 0;
7076 rsurface.texcoordtexture2f_bufferoffset = 0;
7078 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
7079 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7080 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7081 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7084 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7087 const msurface_t *surface = texturesurfacelist[0];
7088 const msurface_t *surface2;
7093 // TODO: lock all array ranges before render, rather than on each surface
7094 if (texturenumsurfaces == 1)
7096 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7097 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);
7099 else if (r_batchmode.integer == 2)
7101 #define MAXBATCHTRIANGLES 4096
7102 int batchtriangles = 0;
7103 static int batchelements[MAXBATCHTRIANGLES*3];
7104 for (i = 0;i < texturenumsurfaces;i = j)
7106 surface = texturesurfacelist[i];
7108 if (surface->num_triangles > MAXBATCHTRIANGLES)
7110 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);
7113 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7114 batchtriangles = surface->num_triangles;
7115 firstvertex = surface->num_firstvertex;
7116 endvertex = surface->num_firstvertex + surface->num_vertices;
7117 for (;j < texturenumsurfaces;j++)
7119 surface2 = texturesurfacelist[j];
7120 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7122 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7123 batchtriangles += surface2->num_triangles;
7124 firstvertex = min(firstvertex, surface2->num_firstvertex);
7125 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7127 surface2 = texturesurfacelist[j-1];
7128 numvertices = endvertex - firstvertex;
7129 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7132 else if (r_batchmode.integer == 1)
7134 for (i = 0;i < texturenumsurfaces;i = j)
7136 surface = texturesurfacelist[i];
7137 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7138 if (texturesurfacelist[j] != surface2)
7140 surface2 = texturesurfacelist[j-1];
7141 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7142 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7143 GL_LockArrays(surface->num_firstvertex, numvertices);
7144 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7149 for (i = 0;i < texturenumsurfaces;i++)
7151 surface = texturesurfacelist[i];
7152 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7153 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);
7158 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
7160 int i, planeindex, vertexindex;
7164 r_waterstate_waterplane_t *p, *bestp;
7165 const msurface_t *surface;
7166 if (r_waterstate.renderingscene)
7168 for (i = 0;i < texturenumsurfaces;i++)
7170 surface = texturesurfacelist[i];
7171 if (lightmaptexunit >= 0)
7172 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7173 if (deluxemaptexunit >= 0)
7174 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7175 // pick the closest matching water plane
7178 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7181 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7183 Matrix4x4_Transform(&rsurface.matrix, v, vert);
7184 d += fabs(PlaneDiff(vert, &p->plane));
7186 if (bestd > d || !bestp)
7194 if (refractiontexunit >= 0)
7195 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
7196 if (reflectiontexunit >= 0)
7197 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
7201 if (refractiontexunit >= 0)
7202 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
7203 if (reflectiontexunit >= 0)
7204 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
7206 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7207 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);
7211 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
7215 const msurface_t *surface = texturesurfacelist[0];
7216 const msurface_t *surface2;
7221 // TODO: lock all array ranges before render, rather than on each surface
7222 if (texturenumsurfaces == 1)
7224 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7225 if (deluxemaptexunit >= 0)
7226 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7227 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7228 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);
7230 else if (r_batchmode.integer == 2)
7232 #define MAXBATCHTRIANGLES 4096
7233 int batchtriangles = 0;
7234 int batchelements[MAXBATCHTRIANGLES*3];
7235 for (i = 0;i < texturenumsurfaces;i = j)
7237 surface = texturesurfacelist[i];
7238 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7239 if (deluxemaptexunit >= 0)
7240 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7242 if (surface->num_triangles > MAXBATCHTRIANGLES)
7244 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);
7247 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7248 batchtriangles = surface->num_triangles;
7249 firstvertex = surface->num_firstvertex;
7250 endvertex = surface->num_firstvertex + surface->num_vertices;
7251 for (;j < texturenumsurfaces;j++)
7253 surface2 = texturesurfacelist[j];
7254 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7256 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7257 batchtriangles += surface2->num_triangles;
7258 firstvertex = min(firstvertex, surface2->num_firstvertex);
7259 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7261 surface2 = texturesurfacelist[j-1];
7262 numvertices = endvertex - firstvertex;
7263 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7266 else if (r_batchmode.integer == 1)
7269 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
7270 for (i = 0;i < texturenumsurfaces;i = j)
7272 surface = texturesurfacelist[i];
7273 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7274 if (texturesurfacelist[j] != surface2)
7276 Con_Printf(" %i", j - i);
7279 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
7281 for (i = 0;i < texturenumsurfaces;i = j)
7283 surface = texturesurfacelist[i];
7284 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7285 if (deluxemaptexunit >= 0)
7286 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7287 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7288 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
7291 Con_Printf(" %i", j - i);
7293 surface2 = texturesurfacelist[j-1];
7294 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7295 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7296 GL_LockArrays(surface->num_firstvertex, numvertices);
7297 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7305 for (i = 0;i < texturenumsurfaces;i++)
7307 surface = texturesurfacelist[i];
7308 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7309 if (deluxemaptexunit >= 0)
7310 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7311 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7312 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);
7317 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7320 int texturesurfaceindex;
7321 if (r_showsurfaces.integer == 2)
7323 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7325 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7326 for (j = 0;j < surface->num_triangles;j++)
7328 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7329 GL_Color(f, f, f, 1);
7330 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7336 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7338 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7339 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7340 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);
7341 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7342 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);
7347 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7349 int texturesurfaceindex;
7353 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7355 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7356 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)
7364 rsurface.lightmapcolor4f = rsurface.array_color4f;
7365 rsurface.lightmapcolor4f_bufferobject = 0;
7366 rsurface.lightmapcolor4f_bufferoffset = 0;
7369 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7371 int texturesurfaceindex;
7377 if (rsurface.lightmapcolor4f)
7379 // generate color arrays for the surfaces in this list
7380 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7382 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7383 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)
7385 f = RSurf_FogVertex(v);
7395 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7397 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7398 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)
7400 f = RSurf_FogVertex(v);
7408 rsurface.lightmapcolor4f = rsurface.array_color4f;
7409 rsurface.lightmapcolor4f_bufferobject = 0;
7410 rsurface.lightmapcolor4f_bufferoffset = 0;
7413 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7415 int texturesurfaceindex;
7421 if (!rsurface.lightmapcolor4f)
7423 // generate color arrays for the surfaces in this list
7424 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7426 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7427 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)
7429 f = RSurf_FogVertex(v);
7430 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7431 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7432 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7436 rsurface.lightmapcolor4f = rsurface.array_color4f;
7437 rsurface.lightmapcolor4f_bufferobject = 0;
7438 rsurface.lightmapcolor4f_bufferoffset = 0;
7441 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7443 int texturesurfaceindex;
7447 if (!rsurface.lightmapcolor4f)
7449 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7451 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7452 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)
7460 rsurface.lightmapcolor4f = rsurface.array_color4f;
7461 rsurface.lightmapcolor4f_bufferobject = 0;
7462 rsurface.lightmapcolor4f_bufferoffset = 0;
7465 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7467 int texturesurfaceindex;
7471 if (!rsurface.lightmapcolor4f)
7473 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7475 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7476 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)
7478 c2[0] = c[0] + r_refdef.scene.ambient;
7479 c2[1] = c[1] + r_refdef.scene.ambient;
7480 c2[2] = c[2] + r_refdef.scene.ambient;
7484 rsurface.lightmapcolor4f = rsurface.array_color4f;
7485 rsurface.lightmapcolor4f_bufferobject = 0;
7486 rsurface.lightmapcolor4f_bufferoffset = 0;
7489 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7492 rsurface.lightmapcolor4f = NULL;
7493 rsurface.lightmapcolor4f_bufferobject = 0;
7494 rsurface.lightmapcolor4f_bufferoffset = 0;
7495 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7496 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7497 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7498 GL_Color(r, g, b, a);
7499 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7502 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7504 // TODO: optimize applyfog && applycolor case
7505 // just apply fog if necessary, and tint the fog color array if necessary
7506 rsurface.lightmapcolor4f = NULL;
7507 rsurface.lightmapcolor4f_bufferobject = 0;
7508 rsurface.lightmapcolor4f_bufferoffset = 0;
7509 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7510 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7511 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7512 GL_Color(r, g, b, a);
7513 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7516 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7518 int texturesurfaceindex;
7522 if (texturesurfacelist[0]->lightmapinfo)
7524 // generate color arrays for the surfaces in this list
7525 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7527 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7528 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7530 if (surface->lightmapinfo->samples)
7532 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7533 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7534 VectorScale(lm, scale, c);
7535 if (surface->lightmapinfo->styles[1] != 255)
7537 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7539 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7540 VectorMA(c, scale, lm, c);
7541 if (surface->lightmapinfo->styles[2] != 255)
7544 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7545 VectorMA(c, scale, lm, c);
7546 if (surface->lightmapinfo->styles[3] != 255)
7549 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7550 VectorMA(c, scale, lm, c);
7560 rsurface.lightmapcolor4f = rsurface.array_color4f;
7561 rsurface.lightmapcolor4f_bufferobject = 0;
7562 rsurface.lightmapcolor4f_bufferoffset = 0;
7566 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7567 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7568 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7570 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7571 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7572 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7573 GL_Color(r, g, b, a);
7574 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7577 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7579 int texturesurfaceindex;
7586 vec3_t ambientcolor;
7587 vec3_t diffusecolor;
7591 VectorCopy(rsurface.modellight_lightdir, lightdir);
7592 f = 0.5f * r_refdef.lightmapintensity;
7593 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7594 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7595 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7596 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7597 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7598 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7600 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7602 // generate color arrays for the surfaces in this list
7603 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7605 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7606 int numverts = surface->num_vertices;
7607 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7608 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7609 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7610 // q3-style directional shading
7611 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7613 if ((f = DotProduct(n, lightdir)) > 0)
7614 VectorMA(ambientcolor, f, diffusecolor, c);
7616 VectorCopy(ambientcolor, c);
7624 rsurface.lightmapcolor4f = rsurface.array_color4f;
7625 rsurface.lightmapcolor4f_bufferobject = 0;
7626 rsurface.lightmapcolor4f_bufferoffset = 0;
7627 *applycolor = false;
7631 *r = ambientcolor[0];
7632 *g = ambientcolor[1];
7633 *b = ambientcolor[2];
7634 rsurface.lightmapcolor4f = NULL;
7635 rsurface.lightmapcolor4f_bufferobject = 0;
7636 rsurface.lightmapcolor4f_bufferoffset = 0;
7640 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7642 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7643 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7644 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7645 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7646 GL_Color(r, g, b, a);
7647 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7650 void RSurf_SetupDepthAndCulling(void)
7652 // submodels are biased to avoid z-fighting with world surfaces that they
7653 // may be exactly overlapping (avoids z-fighting artifacts on certain
7654 // doors and things in Quake maps)
7655 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7656 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7657 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7658 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7661 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7663 // transparent sky would be ridiculous
7664 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7666 R_SetupGenericShader(false);
7667 skyrenderlater = true;
7668 RSurf_SetupDepthAndCulling();
7670 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7671 // skymasking on them, and Quake3 never did sky masking (unlike
7672 // software Quake and software Quake2), so disable the sky masking
7673 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7674 // and skymasking also looks very bad when noclipping outside the
7675 // level, so don't use it then either.
7676 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7678 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7679 R_Mesh_ColorPointer(NULL, 0, 0);
7680 R_Mesh_ResetTextureState();
7681 if (skyrendermasked)
7683 R_SetupDepthOrShadowShader();
7684 // depth-only (masking)
7685 GL_ColorMask(0,0,0,0);
7686 // just to make sure that braindead drivers don't draw
7687 // anything despite that colormask...
7688 GL_BlendFunc(GL_ZERO, GL_ONE);
7692 R_SetupGenericShader(false);
7694 GL_BlendFunc(GL_ONE, GL_ZERO);
7696 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7697 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7698 if (skyrendermasked)
7699 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7701 R_Mesh_ResetTextureState();
7702 GL_Color(1, 1, 1, 1);
7705 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
7706 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
7707 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
7709 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7712 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7713 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7714 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7715 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7716 if (rsurface.texture->backgroundcurrentskinframe)
7718 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7719 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7720 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7721 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7723 if (rsurface.texture->colormapping)
7725 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7726 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7728 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7729 if (r_shadow_usingdeferredprepass)
7731 R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture));
7732 R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture));
7734 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7735 R_Mesh_ColorPointer(NULL, 0, 0);
7737 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7739 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass)
7741 // render background
7742 GL_BlendFunc(GL_ONE, GL_ZERO);
7744 GL_AlphaTest(false);
7746 GL_Color(1, 1, 1, 1);
7747 R_Mesh_ColorPointer(NULL, 0, 0);
7749 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7750 if (r_glsl_permutation)
7752 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7753 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7754 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7755 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7756 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7757 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7758 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);
7760 GL_LockArrays(0, 0);
7762 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7763 GL_DepthMask(false);
7764 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7765 R_Mesh_ColorPointer(NULL, 0, 0);
7767 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7768 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7769 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7772 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
7773 if (!r_glsl_permutation)
7776 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7777 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7778 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7779 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7780 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7782 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7784 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7786 GL_BlendFunc(GL_ONE, GL_ZERO);
7788 GL_AlphaTest(false);
7792 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7793 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7794 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
7797 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7799 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7800 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);
7802 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7806 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7807 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);
7809 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7811 GL_LockArrays(0, 0);
7814 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7816 // OpenGL 1.3 path - anything not completely ancient
7817 int texturesurfaceindex;
7818 qboolean applycolor;
7821 const texturelayer_t *layer;
7822 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7824 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7827 int layertexrgbscale;
7828 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7830 if (layerindex == 0)
7834 GL_AlphaTest(false);
7835 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7838 GL_DepthMask(layer->depthmask && writedepth);
7839 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7840 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7842 layertexrgbscale = 4;
7843 VectorScale(layer->color, 0.25f, layercolor);
7845 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7847 layertexrgbscale = 2;
7848 VectorScale(layer->color, 0.5f, layercolor);
7852 layertexrgbscale = 1;
7853 VectorScale(layer->color, 1.0f, layercolor);
7855 layercolor[3] = layer->color[3];
7856 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7857 R_Mesh_ColorPointer(NULL, 0, 0);
7858 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
7859 switch (layer->type)
7861 case TEXTURELAYERTYPE_LITTEXTURE:
7862 // single-pass lightmapped texture with 2x rgbscale
7863 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
7864 R_Mesh_TexMatrix(0, NULL);
7865 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7866 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7867 R_Mesh_TexBind(1, R_GetTexture(layer->texture));
7868 R_Mesh_TexMatrix(1, &layer->texmatrix);
7869 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7870 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7871 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7872 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7873 else if (rsurface.uselightmaptexture)
7874 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7876 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7878 case TEXTURELAYERTYPE_TEXTURE:
7879 // singletexture unlit texture with transparency support
7880 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7881 R_Mesh_TexMatrix(0, &layer->texmatrix);
7882 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7883 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7884 R_Mesh_TexBind(1, 0);
7885 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
7886 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7888 case TEXTURELAYERTYPE_FOG:
7889 // singletexture fogging
7892 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7893 R_Mesh_TexMatrix(0, &layer->texmatrix);
7894 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7895 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7899 R_Mesh_TexBind(0, 0);
7900 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
7902 R_Mesh_TexBind(1, 0);
7903 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
7904 // generate a color array for the fog pass
7905 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7906 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7912 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7913 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)
7915 f = 1 - RSurf_FogVertex(v);
7916 c[0] = layercolor[0];
7917 c[1] = layercolor[1];
7918 c[2] = layercolor[2];
7919 c[3] = f * layercolor[3];
7922 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7925 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7927 GL_LockArrays(0, 0);
7930 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7932 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7933 GL_AlphaTest(false);
7937 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7939 // OpenGL 1.1 - crusty old voodoo path
7940 int texturesurfaceindex;
7943 const texturelayer_t *layer;
7944 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7946 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7948 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7950 if (layerindex == 0)
7954 GL_AlphaTest(false);
7955 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7958 GL_DepthMask(layer->depthmask && writedepth);
7959 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7960 R_Mesh_ColorPointer(NULL, 0, 0);
7961 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
7962 switch (layer->type)
7964 case TEXTURELAYERTYPE_LITTEXTURE:
7965 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7967 // two-pass lit texture with 2x rgbscale
7968 // first the lightmap pass
7969 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
7970 R_Mesh_TexMatrix(0, NULL);
7971 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7972 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7973 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7974 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7975 else if (rsurface.uselightmaptexture)
7976 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7978 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7979 GL_LockArrays(0, 0);
7980 // then apply the texture to it
7981 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7982 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7983 R_Mesh_TexMatrix(0, &layer->texmatrix);
7984 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7985 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7986 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);
7990 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7991 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7992 R_Mesh_TexMatrix(0, &layer->texmatrix);
7993 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7994 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7995 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7996 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);
7998 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);
8001 case TEXTURELAYERTYPE_TEXTURE:
8002 // singletexture unlit texture with transparency support
8003 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8004 R_Mesh_TexMatrix(0, &layer->texmatrix);
8005 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8006 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8007 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);
8009 case TEXTURELAYERTYPE_FOG:
8010 // singletexture fogging
8013 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8014 R_Mesh_TexMatrix(0, &layer->texmatrix);
8015 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8016 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8020 R_Mesh_TexBind(0, 0);
8021 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8023 // generate a color array for the fog pass
8024 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8025 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8031 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8032 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)
8034 f = 1 - RSurf_FogVertex(v);
8035 c[0] = layer->color[0];
8036 c[1] = layer->color[1];
8037 c[2] = layer->color[2];
8038 c[3] = f * layer->color[3];
8041 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8044 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8046 GL_LockArrays(0, 0);
8049 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8051 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8052 GL_AlphaTest(false);
8056 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8060 GL_AlphaTest(false);
8061 R_Mesh_ColorPointer(NULL, 0, 0);
8062 R_Mesh_ResetTextureState();
8063 R_SetupGenericShader(false);
8065 if(rsurface.texture && rsurface.texture->currentskinframe)
8067 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8068 c[3] *= rsurface.texture->currentalpha;
8078 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
8080 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8081 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8082 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8085 // brighten it up (as texture value 127 means "unlit")
8086 c[0] *= 2 * r_refdef.view.colorscale;
8087 c[1] *= 2 * r_refdef.view.colorscale;
8088 c[2] *= 2 * r_refdef.view.colorscale;
8090 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8091 c[3] *= r_wateralpha.value;
8093 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8095 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8096 GL_DepthMask(false);
8098 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8100 GL_BlendFunc(GL_ONE, GL_ONE);
8101 GL_DepthMask(false);
8103 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8105 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8106 GL_DepthMask(false);
8108 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8110 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8111 GL_DepthMask(false);
8115 GL_BlendFunc(GL_ONE, GL_ZERO);
8116 GL_DepthMask(writedepth);
8119 rsurface.lightmapcolor4f = NULL;
8121 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8123 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8125 rsurface.lightmapcolor4f = NULL;
8126 rsurface.lightmapcolor4f_bufferobject = 0;
8127 rsurface.lightmapcolor4f_bufferoffset = 0;
8129 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8131 qboolean applycolor = true;
8134 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8136 r_refdef.lightmapintensity = 1;
8137 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8138 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8142 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8144 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8145 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8146 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8149 if(!rsurface.lightmapcolor4f)
8150 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8152 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8153 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8154 if(r_refdef.fogenabled)
8155 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8157 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8158 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8161 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8164 RSurf_SetupDepthAndCulling();
8165 if (r_showsurfaces.integer == 3 && !prepass)
8167 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8170 switch (vid.renderpath)
8172 case RENDERPATH_GL20:
8173 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8175 case RENDERPATH_GL13:
8176 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8178 case RENDERPATH_GL11:
8179 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8185 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8188 RSurf_SetupDepthAndCulling();
8189 if (r_showsurfaces.integer == 3 && !prepass)
8191 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8194 switch (vid.renderpath)
8196 case RENDERPATH_GL20:
8197 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8199 case RENDERPATH_GL13:
8200 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8202 case RENDERPATH_GL11:
8203 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8209 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8212 int texturenumsurfaces, endsurface;
8214 const msurface_t *surface;
8215 const msurface_t *texturesurfacelist[256];
8217 // if the model is static it doesn't matter what value we give for
8218 // wantnormals and wanttangents, so this logic uses only rules applicable
8219 // to a model, knowing that they are meaningless otherwise
8220 if (ent == r_refdef.scene.worldentity)
8221 RSurf_ActiveWorldEntity();
8222 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8223 RSurf_ActiveModelEntity(ent, false, false, false);
8226 switch (vid.renderpath)
8228 case RENDERPATH_GL20:
8229 RSurf_ActiveModelEntity(ent, true, true, false);
8231 case RENDERPATH_GL13:
8232 case RENDERPATH_GL11:
8233 RSurf_ActiveModelEntity(ent, true, false, false);
8238 if (r_transparentdepthmasking.integer)
8240 qboolean setup = false;
8241 for (i = 0;i < numsurfaces;i = j)
8244 surface = rsurface.modelsurfaces + surfacelist[i];
8245 texture = surface->texture;
8246 rsurface.texture = R_GetCurrentTexture(texture);
8247 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8248 // scan ahead until we find a different texture
8249 endsurface = min(i + 1024, numsurfaces);
8250 texturenumsurfaces = 0;
8251 texturesurfacelist[texturenumsurfaces++] = surface;
8252 for (;j < endsurface;j++)
8254 surface = rsurface.modelsurfaces + surfacelist[j];
8255 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8257 texturesurfacelist[texturenumsurfaces++] = surface;
8259 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
8261 // render the range of surfaces as depth
8265 GL_ColorMask(0,0,0,0);
8268 GL_BlendFunc(GL_ONE, GL_ZERO);
8270 GL_AlphaTest(false);
8271 R_Mesh_ColorPointer(NULL, 0, 0);
8272 R_Mesh_ResetTextureState();
8273 R_SetupDepthOrShadowShader();
8275 RSurf_SetupDepthAndCulling();
8276 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8277 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8280 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8283 for (i = 0;i < numsurfaces;i = j)
8286 surface = rsurface.modelsurfaces + surfacelist[i];
8287 texture = surface->texture;
8288 rsurface.texture = R_GetCurrentTexture(texture);
8289 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8290 // scan ahead until we find a different texture
8291 endsurface = min(i + 1024, numsurfaces);
8292 texturenumsurfaces = 0;
8293 texturesurfacelist[texturenumsurfaces++] = surface;
8294 for (;j < endsurface;j++)
8296 surface = rsurface.modelsurfaces + surfacelist[j];
8297 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8299 texturesurfacelist[texturenumsurfaces++] = surface;
8301 // render the range of surfaces
8302 if (ent == r_refdef.scene.worldentity)
8303 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8305 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8307 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8308 GL_AlphaTest(false);
8311 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
8313 // transparent surfaces get pushed off into the transparent queue
8314 int surfacelistindex;
8315 const msurface_t *surface;
8316 vec3_t tempcenter, center;
8317 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8319 surface = texturesurfacelist[surfacelistindex];
8320 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8321 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8322 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8323 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8324 if (queueentity->transparent_offset) // transparent offset
8326 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8327 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8328 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8330 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8334 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
8336 const entity_render_t *queueentity = r_refdef.scene.worldentity;
8340 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8342 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8344 RSurf_SetupDepthAndCulling();
8345 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8346 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8350 if (!rsurface.texture->currentnumlayers)
8352 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8353 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8355 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8357 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
8359 RSurf_SetupDepthAndCulling();
8360 GL_AlphaTest(false);
8361 R_Mesh_ColorPointer(NULL, 0, 0);
8362 R_Mesh_ResetTextureState();
8363 R_SetupGenericShader(false);
8364 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8366 GL_BlendFunc(GL_ONE, GL_ZERO);
8367 GL_Color(0, 0, 0, 1);
8368 GL_DepthTest(writedepth);
8369 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8371 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
8373 RSurf_SetupDepthAndCulling();
8374 GL_AlphaTest(false);
8375 R_Mesh_ColorPointer(NULL, 0, 0);
8376 R_Mesh_ResetTextureState();
8377 R_SetupGenericShader(false);
8378 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8380 GL_BlendFunc(GL_ONE, GL_ZERO);
8382 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8384 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8385 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8386 else if (!rsurface.texture->currentnumlayers)
8388 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8390 // in the deferred case, transparent surfaces were queued during prepass
8391 if (!r_shadow_usingdeferredprepass)
8392 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8396 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8397 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8402 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8406 // break the surface list down into batches by texture and use of lightmapping
8407 for (i = 0;i < numsurfaces;i = j)
8410 // texture is the base texture pointer, rsurface.texture is the
8411 // current frame/skin the texture is directing us to use (for example
8412 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8413 // use skin 1 instead)
8414 texture = surfacelist[i]->texture;
8415 rsurface.texture = R_GetCurrentTexture(texture);
8416 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8417 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8419 // if this texture is not the kind we want, skip ahead to the next one
8420 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8424 // simply scan ahead until we find a different texture or lightmap state
8425 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8427 // render the range of surfaces
8428 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
8432 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
8437 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8439 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8441 RSurf_SetupDepthAndCulling();
8442 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8443 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8447 if (!rsurface.texture->currentnumlayers)
8449 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8450 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8452 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8454 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8456 RSurf_SetupDepthAndCulling();
8457 GL_AlphaTest(false);
8458 R_Mesh_ColorPointer(NULL, 0, 0);
8459 R_Mesh_ResetTextureState();
8460 R_SetupGenericShader(false);
8461 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8463 GL_BlendFunc(GL_ONE, GL_ZERO);
8464 GL_Color(0, 0, 0, 1);
8465 GL_DepthTest(writedepth);
8466 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8468 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8470 RSurf_SetupDepthAndCulling();
8471 GL_AlphaTest(false);
8472 R_Mesh_ColorPointer(NULL, 0, 0);
8473 R_Mesh_ResetTextureState();
8474 R_SetupGenericShader(false);
8475 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8477 GL_BlendFunc(GL_ONE, GL_ZERO);
8479 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8481 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8482 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8483 else if (!rsurface.texture->currentnumlayers)
8485 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8487 // in the deferred case, transparent surfaces were queued during prepass
8488 if (!r_shadow_usingdeferredprepass)
8489 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8493 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8494 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8499 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8503 // break the surface list down into batches by texture and use of lightmapping
8504 for (i = 0;i < numsurfaces;i = j)
8507 // texture is the base texture pointer, rsurface.texture is the
8508 // current frame/skin the texture is directing us to use (for example
8509 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8510 // use skin 1 instead)
8511 texture = surfacelist[i]->texture;
8512 rsurface.texture = R_GetCurrentTexture(texture);
8513 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8514 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8516 // if this texture is not the kind we want, skip ahead to the next one
8517 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8521 // simply scan ahead until we find a different texture or lightmap state
8522 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8524 // render the range of surfaces
8525 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
8529 float locboxvertex3f[6*4*3] =
8531 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8532 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8533 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8534 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8535 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8536 1,0,0, 0,0,0, 0,1,0, 1,1,0
8539 unsigned short locboxelements[6*2*3] =
8549 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8552 cl_locnode_t *loc = (cl_locnode_t *)ent;
8554 float vertex3f[6*4*3];
8556 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8557 GL_DepthMask(false);
8558 GL_DepthRange(0, 1);
8559 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8561 GL_CullFace(GL_NONE);
8562 R_Mesh_Matrix(&identitymatrix);
8564 R_Mesh_VertexPointer(vertex3f, 0, 0);
8565 R_Mesh_ColorPointer(NULL, 0, 0);
8566 R_Mesh_ResetTextureState();
8567 R_SetupGenericShader(false);
8570 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8571 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8572 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8573 surfacelist[0] < 0 ? 0.5f : 0.125f);
8575 if (VectorCompare(loc->mins, loc->maxs))
8577 VectorSet(size, 2, 2, 2);
8578 VectorMA(loc->mins, -0.5f, size, mins);
8582 VectorCopy(loc->mins, mins);
8583 VectorSubtract(loc->maxs, loc->mins, size);
8586 for (i = 0;i < 6*4*3;)
8587 for (j = 0;j < 3;j++, i++)
8588 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8590 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8593 void R_DrawLocs(void)
8596 cl_locnode_t *loc, *nearestloc;
8598 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8599 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8601 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8602 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8606 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8608 if (decalsystem->decals)
8609 Mem_Free(decalsystem->decals);
8610 memset(decalsystem, 0, sizeof(*decalsystem));
8613 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, int decalsequence)
8620 // expand or initialize the system
8621 if (decalsystem->maxdecals <= decalsystem->numdecals)
8623 decalsystem_t old = *decalsystem;
8624 qboolean useshortelements;
8625 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8626 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8627 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)));
8628 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8629 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8630 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8631 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8632 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8633 if (decalsystem->numdecals)
8634 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8636 Mem_Free(old.decals);
8637 for (i = 0;i < decalsystem->maxdecals*3;i++)
8638 decalsystem->element3i[i] = i;
8639 if (useshortelements)
8640 for (i = 0;i < decalsystem->maxdecals*3;i++)
8641 decalsystem->element3s[i] = i;
8644 // grab a decal and search for another free slot for the next one
8645 maxdecals = decalsystem->maxdecals;
8646 decals = decalsystem->decals;
8647 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8648 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8650 decalsystem->freedecal = i;
8651 if (decalsystem->numdecals <= i)
8652 decalsystem->numdecals = i + 1;
8654 // initialize the decal
8656 decal->triangleindex = triangleindex;
8657 decal->surfaceindex = surfaceindex;
8658 decal->decalsequence = decalsequence;
8659 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8660 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8661 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8662 decal->color4ub[0][3] = 255;
8663 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8664 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8665 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8666 decal->color4ub[1][3] = 255;
8667 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8668 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8669 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8670 decal->color4ub[2][3] = 255;
8671 decal->vertex3f[0][0] = v0[0];
8672 decal->vertex3f[0][1] = v0[1];
8673 decal->vertex3f[0][2] = v0[2];
8674 decal->vertex3f[1][0] = v1[0];
8675 decal->vertex3f[1][1] = v1[1];
8676 decal->vertex3f[1][2] = v1[2];
8677 decal->vertex3f[2][0] = v2[0];
8678 decal->vertex3f[2][1] = v2[1];
8679 decal->vertex3f[2][2] = v2[2];
8680 decal->texcoord2f[0][0] = t0[0];
8681 decal->texcoord2f[0][1] = t0[1];
8682 decal->texcoord2f[1][0] = t1[0];
8683 decal->texcoord2f[1][1] = t1[1];
8684 decal->texcoord2f[2][0] = t2[0];
8685 decal->texcoord2f[2][1] = t2[1];
8688 extern cvar_t cl_decals_bias;
8689 extern cvar_t cl_decals_models;
8690 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8691 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
8693 matrix4x4_t projection;
8694 decalsystem_t *decalsystem;
8697 const float *vertex3f;
8698 const msurface_t *surface;
8699 const msurface_t *surfaces;
8700 const int *surfacelist;
8701 const texture_t *texture;
8705 int surfacelistindex;
8708 int decalsurfaceindex;
8713 float localorigin[3];
8714 float localnormal[3];
8725 float points[2][9][3];
8729 decalsystem = &ent->decalsystem;
8731 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8733 R_DecalSystem_Reset(&ent->decalsystem);
8737 if (!model->brush.data_nodes && !cl_decals_models.integer)
8739 if (decalsystem->model)
8740 R_DecalSystem_Reset(decalsystem);
8744 if (decalsystem->model != model)
8745 R_DecalSystem_Reset(decalsystem);
8746 decalsystem->model = model;
8748 RSurf_ActiveModelEntity(ent, false, false, false);
8750 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8751 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8752 VectorNormalize(localnormal);
8753 localsize = worldsize*rsurface.inversematrixscale;
8754 ilocalsize = 1.0f / localsize;
8755 localmins[0] = localorigin[0] - localsize;
8756 localmins[1] = localorigin[1] - localsize;
8757 localmins[2] = localorigin[2] - localsize;
8758 localmaxs[0] = localorigin[0] + localsize;
8759 localmaxs[1] = localorigin[1] + localsize;
8760 localmaxs[2] = localorigin[2] + localsize;
8762 //VectorCopy(localnormal, planes[4]);
8763 //VectorVectors(planes[4], planes[2], planes[0]);
8764 AnglesFromVectors(angles, localnormal, NULL, false);
8765 AngleVectors(angles, planes[0], planes[2], planes[4]);
8766 VectorNegate(planes[0], planes[1]);
8767 VectorNegate(planes[2], planes[3]);
8768 VectorNegate(planes[4], planes[5]);
8769 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8770 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8771 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8772 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8773 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8774 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8779 matrix4x4_t forwardprojection;
8780 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8781 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8786 float projectionvector[4][3];
8787 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8788 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8789 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8790 projectionvector[0][0] = planes[0][0] * ilocalsize;
8791 projectionvector[0][1] = planes[1][0] * ilocalsize;
8792 projectionvector[0][2] = planes[2][0] * ilocalsize;
8793 projectionvector[1][0] = planes[0][1] * ilocalsize;
8794 projectionvector[1][1] = planes[1][1] * ilocalsize;
8795 projectionvector[1][2] = planes[2][1] * ilocalsize;
8796 projectionvector[2][0] = planes[0][2] * ilocalsize;
8797 projectionvector[2][1] = planes[1][2] * ilocalsize;
8798 projectionvector[2][2] = planes[2][2] * ilocalsize;
8799 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8800 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8801 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8802 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8806 dynamic = model->surfmesh.isanimated;
8807 vertex3f = rsurface.modelvertex3f;
8808 numsurfacelist = model->nummodelsurfaces;
8809 surfacelist = model->sortedmodelsurfaces;
8810 surfaces = model->data_surfaces;
8811 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8813 surfaceindex = surfacelist[surfacelistindex];
8814 surface = surfaces + surfaceindex;
8815 // skip transparent surfaces
8816 texture = surface->texture;
8817 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8819 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8821 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8823 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8824 numvertices = surface->num_vertices;
8825 numtriangles = surface->num_triangles;
8826 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8828 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8830 index = 3*e[cornerindex];
8831 VectorCopy(vertex3f + index, v[cornerindex]);
8834 //TriangleNormal(v[0], v[1], v[2], normal);
8835 //if (DotProduct(normal, localnormal) < 0.0f)
8837 // clip by each of the box planes formed from the projection matrix
8838 // if anything survives, we emit the decal
8839 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]);
8842 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]);
8845 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]);
8848 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]);
8851 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]);
8854 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]);
8857 // some part of the triangle survived, so we have to accept it...
8860 // dynamic always uses the original triangle
8862 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8864 index = 3*e[cornerindex];
8865 VectorCopy(vertex3f + index, v[cornerindex]);
8868 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8870 // convert vertex positions to texcoords
8871 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8872 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8873 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8874 // calculate distance fade from the projection origin
8875 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8876 f = bound(0.0f, f, 1.0f);
8877 c[cornerindex][0] = r * f;
8878 c[cornerindex][1] = g * f;
8879 c[cornerindex][2] = b * f;
8880 c[cornerindex][3] = 1.0f;
8881 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8884 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex+surface->num_firsttriangle, surfaceindex, decalsequence);
8886 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8887 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
8892 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8893 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
8895 int renderentityindex;
8898 entity_render_t *ent;
8900 if (!cl_decals_newsystem.integer)
8903 worldmins[0] = worldorigin[0] - worldsize;
8904 worldmins[1] = worldorigin[1] - worldsize;
8905 worldmins[2] = worldorigin[2] - worldsize;
8906 worldmaxs[0] = worldorigin[0] + worldsize;
8907 worldmaxs[1] = worldorigin[1] + worldsize;
8908 worldmaxs[2] = worldorigin[2] + worldsize;
8910 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8912 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8914 ent = r_refdef.scene.entities[renderentityindex];
8915 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8918 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8922 typedef struct r_decalsystem_splatqueue_s
8931 r_decalsystem_splatqueue_t;
8933 int r_decalsystem_numqueued = 0;
8934 #define MAX_DECALSYSTEM_QUEUE 1024
8935 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8937 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)
8939 r_decalsystem_splatqueue_t *queue;
8941 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8944 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8945 VectorCopy(worldorigin, queue->worldorigin);
8946 VectorCopy(worldnormal, queue->worldnormal);
8947 Vector4Set(queue->color, r, g, b, a);
8948 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8949 queue->worldsize = worldsize;
8950 queue->decalsequence = cl.decalsequence++;
8953 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8956 r_decalsystem_splatqueue_t *queue;
8958 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8959 R_DecalSystem_ApplySplatEntities(queue->worldorigin, queue->worldnormal, queue->color[0], queue->color[1], queue->color[2], queue->color[3], queue->tcrange[0], queue->tcrange[1], queue->tcrange[2], queue->tcrange[3], queue->worldsize, queue->decalsequence);
8960 r_decalsystem_numqueued = 0;
8963 extern cvar_t cl_decals_max;
8964 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8967 decalsystem_t *decalsystem = &ent->decalsystem;
8974 if (!decalsystem->numdecals)
8977 if (r_showsurfaces.integer)
8980 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8982 R_DecalSystem_Reset(decalsystem);
8986 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
8987 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
8989 if (decalsystem->lastupdatetime)
8990 frametime = (cl.time - decalsystem->lastupdatetime);
8993 decalsystem->lastupdatetime = cl.time;
8994 decal = decalsystem->decals;
8995 numdecals = decalsystem->numdecals;
8997 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8999 if (decal->color4ub[0][3])
9001 decal->lived += frametime;
9002 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
9004 memset(decal, 0, sizeof(*decal));
9005 if (decalsystem->freedecal > i)
9006 decalsystem->freedecal = i;
9010 decal = decalsystem->decals;
9011 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
9014 // collapse the array by shuffling the tail decals into the gaps
9017 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
9018 decalsystem->freedecal++;
9019 if (decalsystem->freedecal == numdecals)
9021 decal[decalsystem->freedecal] = decal[--numdecals];
9024 decalsystem->numdecals = numdecals;
9028 // if there are no decals left, reset decalsystem
9029 R_DecalSystem_Reset(decalsystem);
9033 extern skinframe_t *decalskinframe;
9034 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9037 decalsystem_t *decalsystem = &ent->decalsystem;
9047 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9050 numdecals = decalsystem->numdecals;
9054 if (r_showsurfaces.integer)
9057 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9059 R_DecalSystem_Reset(decalsystem);
9063 // if the model is static it doesn't matter what value we give for
9064 // wantnormals and wanttangents, so this logic uses only rules applicable
9065 // to a model, knowing that they are meaningless otherwise
9066 if (ent == r_refdef.scene.worldentity)
9067 RSurf_ActiveWorldEntity();
9069 RSurf_ActiveModelEntity(ent, false, false, false);
9071 decalsystem->lastupdatetime = cl.time;
9072 decal = decalsystem->decals;
9074 fadedelay = cl_decals_time.value;
9075 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9077 // update vertex positions for animated models
9078 v3f = decalsystem->vertex3f;
9079 c4f = decalsystem->color4f;
9080 t2f = decalsystem->texcoord2f;
9081 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9083 if (!decal->color4ub[0][3])
9086 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9089 // update color values for fading decals
9090 if (decal->lived >= cl_decals_time.value)
9092 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9093 alpha *= (1.0f/255.0f);
9096 alpha = 1.0f/255.0f;
9098 c4f[ 0] = decal->color4ub[0][0] * alpha;
9099 c4f[ 1] = decal->color4ub[0][1] * alpha;
9100 c4f[ 2] = decal->color4ub[0][2] * alpha;
9102 c4f[ 4] = decal->color4ub[1][0] * alpha;
9103 c4f[ 5] = decal->color4ub[1][1] * alpha;
9104 c4f[ 6] = decal->color4ub[1][2] * alpha;
9106 c4f[ 8] = decal->color4ub[2][0] * alpha;
9107 c4f[ 9] = decal->color4ub[2][1] * alpha;
9108 c4f[10] = decal->color4ub[2][2] * alpha;
9111 t2f[0] = decal->texcoord2f[0][0];
9112 t2f[1] = decal->texcoord2f[0][1];
9113 t2f[2] = decal->texcoord2f[1][0];
9114 t2f[3] = decal->texcoord2f[1][1];
9115 t2f[4] = decal->texcoord2f[2][0];
9116 t2f[5] = decal->texcoord2f[2][1];
9118 // update vertex positions for animated models
9119 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9121 e = rsurface.modelelement3i + 3*decal->triangleindex;
9122 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9123 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9124 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9128 VectorCopy(decal->vertex3f[0], v3f);
9129 VectorCopy(decal->vertex3f[1], v3f + 3);
9130 VectorCopy(decal->vertex3f[2], v3f + 6);
9141 r_refdef.stats.drawndecals += numtris;
9143 if (r_refdef.fogenabled)
9145 switch(vid.renderpath)
9147 case RENDERPATH_GL20:
9148 case RENDERPATH_GL13:
9149 case RENDERPATH_GL11:
9150 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
9152 alpha = RSurf_FogVertex(v3f);
9161 // now render the decals all at once
9162 // (this assumes they all use one particle font texture!)
9163 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
9164 R_Mesh_ResetTextureState();
9165 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9166 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9167 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9168 R_SetupGenericShader(true);
9169 GL_DepthMask(false);
9170 GL_DepthRange(0, 1);
9171 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9173 GL_CullFace(GL_NONE);
9174 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9175 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
9176 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
9177 GL_LockArrays(0, numtris * 3);
9178 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9179 GL_LockArrays(0, 0);
9183 static void R_DrawModelDecals(void)
9187 // fade faster when there are too many decals
9188 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9189 for (i = 0;i < r_refdef.scene.numentities;i++)
9190 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9192 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9193 for (i = 0;i < r_refdef.scene.numentities;i++)
9194 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9195 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9197 R_DecalSystem_ApplySplatEntitiesQueue();
9199 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9200 for (i = 0;i < r_refdef.scene.numentities;i++)
9201 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9203 r_refdef.stats.totaldecals += numdecals;
9205 if (r_showsurfaces.integer)
9208 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9210 for (i = 0;i < r_refdef.scene.numentities;i++)
9212 if (!r_refdef.viewcache.entityvisible[i])
9214 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9215 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9219 void R_DrawDebugModel(void)
9221 entity_render_t *ent = rsurface.entity;
9222 int i, j, k, l, flagsmask;
9223 const int *elements;
9225 const msurface_t *surface;
9226 dp_model_t *model = ent->model;
9229 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9231 R_Mesh_ColorPointer(NULL, 0, 0);
9232 R_Mesh_ResetTextureState();
9233 R_SetupGenericShader(false);
9234 GL_DepthRange(0, 1);
9235 GL_DepthTest(!r_showdisabledepthtest.integer);
9236 GL_DepthMask(false);
9237 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9239 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
9241 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
9242 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
9244 if (brush->colbrushf && brush->colbrushf->numtriangles)
9246 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
9247 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);
9248 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
9251 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
9253 if (surface->num_collisiontriangles)
9255 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
9256 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);
9257 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
9262 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9264 if (r_showtris.integer || r_shownormals.integer)
9266 if (r_showdisabledepthtest.integer)
9268 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9269 GL_DepthMask(false);
9273 GL_BlendFunc(GL_ONE, GL_ZERO);
9276 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9278 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9280 rsurface.texture = R_GetCurrentTexture(surface->texture);
9281 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9283 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
9284 if (r_showtris.value > 0)
9286 if (!rsurface.texture->currentlayers->depthmask)
9287 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
9288 else if (ent == r_refdef.scene.worldentity)
9289 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
9291 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
9292 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
9293 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
9294 R_Mesh_ColorPointer(NULL, 0, 0);
9295 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
9296 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9297 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
9298 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);
9299 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9302 if (r_shownormals.value < 0)
9305 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9307 VectorCopy(rsurface.vertex3f + l * 3, v);
9308 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9309 qglVertex3f(v[0], v[1], v[2]);
9310 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
9311 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9312 qglVertex3f(v[0], v[1], v[2]);
9317 if (r_shownormals.value > 0)
9320 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9322 VectorCopy(rsurface.vertex3f + l * 3, v);
9323 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9324 qglVertex3f(v[0], v[1], v[2]);
9325 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
9326 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9327 qglVertex3f(v[0], v[1], v[2]);
9332 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9334 VectorCopy(rsurface.vertex3f + l * 3, v);
9335 GL_Color(0, r_refdef.view.colorscale, 0, 1);
9336 qglVertex3f(v[0], v[1], v[2]);
9337 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
9338 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9339 qglVertex3f(v[0], v[1], v[2]);
9344 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9346 VectorCopy(rsurface.vertex3f + l * 3, v);
9347 GL_Color(0, 0, r_refdef.view.colorscale, 1);
9348 qglVertex3f(v[0], v[1], v[2]);
9349 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
9350 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9351 qglVertex3f(v[0], v[1], v[2]);
9358 rsurface.texture = NULL;
9362 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
9363 int r_maxsurfacelist = 0;
9364 const msurface_t **r_surfacelist = NULL;
9365 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9367 int i, j, endj, f, flagsmask;
9369 dp_model_t *model = r_refdef.scene.worldmodel;
9370 msurface_t *surfaces;
9371 unsigned char *update;
9372 int numsurfacelist = 0;
9376 if (r_maxsurfacelist < model->num_surfaces)
9378 r_maxsurfacelist = model->num_surfaces;
9380 Mem_Free((msurface_t**)r_surfacelist);
9381 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9384 RSurf_ActiveWorldEntity();
9386 surfaces = model->data_surfaces;
9387 update = model->brushq1.lightmapupdateflags;
9389 // update light styles on this submodel
9390 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9392 model_brush_lightstyleinfo_t *style;
9393 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9395 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9397 int *list = style->surfacelist;
9398 style->value = r_refdef.scene.lightstylevalue[style->style];
9399 for (j = 0;j < style->numsurfaces;j++)
9400 update[list[j]] = true;
9405 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9410 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9416 rsurface.uselightmaptexture = false;
9417 rsurface.texture = NULL;
9418 rsurface.rtlight = NULL;
9420 // add visible surfaces to draw list
9421 for (i = 0;i < model->nummodelsurfaces;i++)
9423 j = model->sortedmodelsurfaces[i];
9424 if (r_refdef.viewcache.world_surfacevisible[j])
9425 r_surfacelist[numsurfacelist++] = surfaces + j;
9427 // update lightmaps if needed
9431 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9433 if (r_refdef.viewcache.world_surfacevisible[j])
9438 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9444 int count = model->brushq3.num_mergedlightmaps;
9445 for (i = 0;i < count;i++)
9447 if (model->brushq3.data_deluxemaps[i])
9448 R_FlushTexture(model->brushq3.data_deluxemaps[i]);
9449 if (model->brushq3.data_lightmaps[i])
9450 R_FlushTexture(model->brushq3.data_lightmaps[i]);
9454 // don't do anything if there were no surfaces
9455 if (!numsurfacelist)
9457 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9460 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9461 GL_AlphaTest(false);
9463 // add to stats if desired
9464 if (r_speeds.integer && !skysurfaces && !depthonly)
9466 r_refdef.stats.world_surfaces += numsurfacelist;
9467 for (j = 0;j < numsurfacelist;j++)
9468 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9471 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9474 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9476 int i, j, endj, f, flagsmask;
9478 dp_model_t *model = ent->model;
9479 msurface_t *surfaces;
9480 unsigned char *update;
9481 int numsurfacelist = 0;
9485 if (r_maxsurfacelist < model->num_surfaces)
9487 r_maxsurfacelist = model->num_surfaces;
9489 Mem_Free((msurface_t **)r_surfacelist);
9490 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9493 // if the model is static it doesn't matter what value we give for
9494 // wantnormals and wanttangents, so this logic uses only rules applicable
9495 // to a model, knowing that they are meaningless otherwise
9496 if (ent == r_refdef.scene.worldentity)
9497 RSurf_ActiveWorldEntity();
9498 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9499 RSurf_ActiveModelEntity(ent, false, false, false);
9501 RSurf_ActiveModelEntity(ent, true, true, true);
9503 RSurf_ActiveModelEntity(ent, false, false, false);
9506 switch (vid.renderpath)
9508 case RENDERPATH_GL20:
9509 RSurf_ActiveModelEntity(ent, true, true, false);
9511 case RENDERPATH_GL13:
9512 case RENDERPATH_GL11:
9513 RSurf_ActiveModelEntity(ent, true, false, false);
9518 surfaces = model->data_surfaces;
9519 update = model->brushq1.lightmapupdateflags;
9521 // update light styles
9522 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9524 model_brush_lightstyleinfo_t *style;
9525 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9527 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9529 int *list = style->surfacelist;
9530 style->value = r_refdef.scene.lightstylevalue[style->style];
9531 for (j = 0;j < style->numsurfaces;j++)
9532 update[list[j]] = true;
9537 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9542 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9548 rsurface.uselightmaptexture = false;
9549 rsurface.texture = NULL;
9550 rsurface.rtlight = NULL;
9552 // add visible surfaces to draw list
9553 for (i = 0;i < model->nummodelsurfaces;i++)
9554 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9555 // don't do anything if there were no surfaces
9556 if (!numsurfacelist)
9558 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9561 // update lightmaps if needed
9565 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9570 R_BuildLightMap(ent, surfaces + j);
9575 int count = model->brushq3.num_mergedlightmaps;
9576 for (i = 0;i < count;i++)
9578 if (model->brushq3.data_deluxemaps[i])
9579 R_FlushTexture(model->brushq3.data_deluxemaps[i]);
9580 if (model->brushq3.data_lightmaps[i])
9581 R_FlushTexture(model->brushq3.data_lightmaps[i]);
9586 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9588 R_BuildLightMap(ent, surfaces + j);
9589 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9590 GL_AlphaTest(false);
9592 // add to stats if desired
9593 if (r_speeds.integer && !skysurfaces && !depthonly)
9595 r_refdef.stats.entities_surfaces += numsurfacelist;
9596 for (j = 0;j < numsurfacelist;j++)
9597 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9600 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9603 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
9605 static texture_t texture;
9606 static msurface_t surface;
9607 const msurface_t *surfacelist = &surface;
9609 // fake enough texture and surface state to render this geometry
9611 texture.update_lastrenderframe = -1; // regenerate this texture
9612 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9613 texture.currentskinframe = skinframe;
9614 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9615 texture.specularscalemod = 1;
9616 texture.specularpowermod = 1;
9618 surface.texture = &texture;
9619 surface.num_triangles = numtriangles;
9620 surface.num_firsttriangle = firsttriangle;
9621 surface.num_vertices = numvertices;
9622 surface.num_firstvertex = firstvertex;
9625 rsurface.texture = R_GetCurrentTexture(surface.texture);
9626 rsurface.uselightmaptexture = false;
9627 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
9630 void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
9632 static msurface_t surface;
9633 const msurface_t *surfacelist = &surface;
9635 // fake enough texture and surface state to render this geometry
9637 surface.texture = texture;
9638 surface.num_triangles = numtriangles;
9639 surface.num_firsttriangle = firsttriangle;
9640 surface.num_vertices = numvertices;
9641 surface.num_firstvertex = firstvertex;
9644 rsurface.texture = R_GetCurrentTexture(surface.texture);
9645 rsurface.uselightmaptexture = false;
9646 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);