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"
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
32 static int r_frame = 0; ///< used only by R_GetCurrentTexture
34 qboolean r_loadnormalmap;
43 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
44 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
45 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
46 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
47 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)"};
48 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
49 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
50 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
52 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
53 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"};
54 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
55 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)"};
56 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
58 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"};
59 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
60 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
61 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
62 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
63 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
64 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)"};
65 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
66 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
67 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"};
68 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"};
69 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
70 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"};
71 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"};
72 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"};
73 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
74 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
75 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
76 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
77 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)"};
78 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)"};
79 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
80 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
81 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
82 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
83 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
84 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
85 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
86 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."};
87 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
88 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
89 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
90 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."};
91 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
92 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
93 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"};
94 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"};
95 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
96 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
97 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
98 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
99 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"};
101 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
102 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
103 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
104 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
105 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
106 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
107 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
108 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
110 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
111 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
112 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
114 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
115 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
116 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
117 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
118 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
119 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
120 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
121 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
122 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
124 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
125 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
126 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
127 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
128 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
130 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
131 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
132 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
133 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
135 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
136 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
137 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
138 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
139 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
140 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
141 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
143 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
144 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
145 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
146 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
148 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
150 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
152 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
154 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
155 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
156 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
157 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
158 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
159 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
160 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
162 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)"};
164 extern cvar_t v_glslgamma;
166 extern qboolean v_flipped_state;
168 static struct r_bloomstate_s
173 int bloomwidth, bloomheight;
175 int screentexturewidth, screentextureheight;
176 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
178 int bloomtexturewidth, bloomtextureheight;
179 rtexture_t *texture_bloom;
181 // arrays for rendering the screen passes
182 float screentexcoord2f[8];
183 float bloomtexcoord2f[8];
184 float offsettexcoord2f[8];
186 r_viewport_t viewport;
190 r_waterstate_t r_waterstate;
192 /// shadow volume bsp struct with automatically growing nodes buffer
195 rtexture_t *r_texture_blanknormalmap;
196 rtexture_t *r_texture_white;
197 rtexture_t *r_texture_grey128;
198 rtexture_t *r_texture_black;
199 rtexture_t *r_texture_notexture;
200 rtexture_t *r_texture_whitecube;
201 rtexture_t *r_texture_normalizationcube;
202 rtexture_t *r_texture_fogattenuation;
203 rtexture_t *r_texture_gammaramps;
204 unsigned int r_texture_gammaramps_serial;
205 //rtexture_t *r_texture_fogintensity;
207 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
208 unsigned int r_numqueries;
209 unsigned int r_maxqueries;
211 typedef struct r_qwskincache_s
213 char name[MAX_QPATH];
214 skinframe_t *skinframe;
218 static r_qwskincache_t *r_qwskincache;
219 static int r_qwskincache_size;
221 /// vertex coordinates for a quad that covers the screen exactly
222 const float r_screenvertex3f[12] =
230 extern void R_DrawModelShadows(void);
232 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
235 for (i = 0;i < verts;i++)
246 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
249 for (i = 0;i < verts;i++)
259 // FIXME: move this to client?
262 if (gamemode == GAME_NEHAHRA)
264 Cvar_Set("gl_fogenable", "0");
265 Cvar_Set("gl_fogdensity", "0.2");
266 Cvar_Set("gl_fogred", "0.3");
267 Cvar_Set("gl_foggreen", "0.3");
268 Cvar_Set("gl_fogblue", "0.3");
270 r_refdef.fog_density = 0;
271 r_refdef.fog_red = 0;
272 r_refdef.fog_green = 0;
273 r_refdef.fog_blue = 0;
274 r_refdef.fog_alpha = 1;
275 r_refdef.fog_start = 0;
276 r_refdef.fog_end = 16384;
277 r_refdef.fog_height = 1<<30;
278 r_refdef.fog_fadedepth = 128;
281 static void R_BuildBlankTextures(void)
283 unsigned char data[4];
284 data[2] = 128; // normal X
285 data[1] = 128; // normal Y
286 data[0] = 255; // normal Z
287 data[3] = 128; // height
288 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
293 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
298 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
303 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
306 static void R_BuildNoTexture(void)
309 unsigned char pix[16][16][4];
310 // this makes a light grey/dark grey checkerboard texture
311 for (y = 0;y < 16;y++)
313 for (x = 0;x < 16;x++)
315 if ((y < 8) ^ (x < 8))
331 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
334 static void R_BuildWhiteCube(void)
336 unsigned char data[6*1*1*4];
337 memset(data, 255, sizeof(data));
338 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
341 static void R_BuildNormalizationCube(void)
345 vec_t s, t, intensity;
348 data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
349 for (side = 0;side < 6;side++)
351 for (y = 0;y < NORMSIZE;y++)
353 for (x = 0;x < NORMSIZE;x++)
355 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
356 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
391 intensity = 127.0f / sqrt(DotProduct(v, v));
392 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
393 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
394 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
395 data[((side*64+y)*64+x)*4+3] = 255;
399 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
403 static void R_BuildFogTexture(void)
407 unsigned char data1[FOGWIDTH][4];
408 //unsigned char data2[FOGWIDTH][4];
411 r_refdef.fogmasktable_start = r_refdef.fog_start;
412 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
413 r_refdef.fogmasktable_range = r_refdef.fogrange;
414 r_refdef.fogmasktable_density = r_refdef.fog_density;
416 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
417 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
419 d = (x * r - r_refdef.fogmasktable_start);
420 if(developer.integer >= 100)
421 Con_Printf("%f ", d);
423 if (r_fog_exp2.integer)
424 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
426 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
427 if(developer.integer >= 100)
428 Con_Printf(" : %f ", alpha);
429 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
430 if(developer.integer >= 100)
431 Con_Printf(" = %f\n", alpha);
432 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
435 for (x = 0;x < FOGWIDTH;x++)
437 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
442 //data2[x][0] = 255 - b;
443 //data2[x][1] = 255 - b;
444 //data2[x][2] = 255 - b;
447 if (r_texture_fogattenuation)
449 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
450 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
454 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
455 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
459 //=======================================================================================================================================================
461 static const char *builtinshaderstring =
462 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
463 "// written by Forest 'LordHavoc' Hale\n"
464 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
466 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
469 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
470 "#define USELIGHTMAP\n"
472 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
473 "#define USEEYEVECTOR\n"
476 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
477 "# extension GL_ARB_texture_rectangle : enable\n"
480 "#ifdef USESHADOWMAP2D\n"
481 "# ifdef GL_EXT_gpu_shader4\n"
482 "# extension GL_EXT_gpu_shader4 : enable\n"
484 "# ifdef GL_ARB_texture_gather\n"
485 "# extension GL_ARB_texture_gather : enable\n"
487 "# ifdef GL_AMD_texture_texture4\n"
488 "# extension GL_AMD_texture_texture4 : enable\n"
493 "#ifdef USESHADOWMAPCUBE\n"
494 "# extension GL_EXT_gpu_shader4 : enable\n"
497 "#ifdef USESHADOWSAMPLER\n"
498 "# extension GL_ARB_shadow : enable\n"
501 "//#ifdef __GLSL_CG_DATA_TYPES\n"
502 "//# define myhalf half\n"
503 "//# define myhalf2 half2\n"
504 "//# define myhalf3 half3\n"
505 "//# define myhalf4 half4\n"
507 "# define myhalf float\n"
508 "# define myhalf2 vec2\n"
509 "# define myhalf3 vec3\n"
510 "# define myhalf4 vec4\n"
513 "#ifdef VERTEX_SHADER\n"
514 "uniform mat4 ModelViewProjectionMatrix;\n"
517 "#ifdef MODE_DEPTH_OR_SHADOW\n"
518 "#ifdef VERTEX_SHADER\n"
521 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
524 "#else // !MODE_DEPTH_ORSHADOW\n"
529 "#ifdef MODE_SHOWDEPTH\n"
530 "#ifdef VERTEX_SHADER\n"
533 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
534 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
538 "#ifdef FRAGMENT_SHADER\n"
541 " gl_FragColor = gl_Color;\n"
544 "#else // !MODE_SHOWDEPTH\n"
549 "#ifdef MODE_POSTPROCESS\n"
550 "varying vec2 TexCoord1;\n"
551 "varying vec2 TexCoord2;\n"
553 "#ifdef VERTEX_SHADER\n"
556 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
557 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
559 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
564 "#ifdef FRAGMENT_SHADER\n"
565 "uniform sampler2D Texture_First;\n"
567 "uniform sampler2D Texture_Second;\n"
569 "#ifdef USEGAMMARAMPS\n"
570 "uniform sampler2D Texture_GammaRamps;\n"
572 "#ifdef USESATURATION\n"
573 "uniform float Saturation;\n"
575 "#ifdef USEVIEWTINT\n"
576 "uniform vec4 ViewTintColor;\n"
578 "//uncomment these if you want to use them:\n"
579 "uniform vec4 UserVec1;\n"
580 "// uniform vec4 UserVec2;\n"
581 "// uniform vec4 UserVec3;\n"
582 "// uniform vec4 UserVec4;\n"
583 "// uniform float ClientTime;\n"
584 "uniform vec2 PixelSize;\n"
587 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
589 " gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
591 "#ifdef USEVIEWTINT\n"
592 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
595 "#ifdef USEPOSTPROCESSING\n"
596 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
597 "// 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"
598 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
599 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
600 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
601 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
602 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
603 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
606 "#ifdef USESATURATION\n"
607 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
608 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
609 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
610 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
613 "#ifdef USEGAMMARAMPS\n"
614 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
615 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
616 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
620 "#else // !MODE_POSTPROCESS\n"
625 "#ifdef MODE_GENERIC\n"
626 "#ifdef USEDIFFUSE\n"
627 "varying vec2 TexCoord1;\n"
629 "#ifdef USESPECULAR\n"
630 "varying vec2 TexCoord2;\n"
632 "#ifdef VERTEX_SHADER\n"
635 " gl_FrontColor = gl_Color;\n"
636 "#ifdef USEDIFFUSE\n"
637 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
639 "#ifdef USESPECULAR\n"
640 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
642 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
646 "#ifdef FRAGMENT_SHADER\n"
647 "#ifdef USEDIFFUSE\n"
648 "uniform sampler2D Texture_First;\n"
650 "#ifdef USESPECULAR\n"
651 "uniform sampler2D Texture_Second;\n"
656 " gl_FragColor = gl_Color;\n"
657 "#ifdef USEDIFFUSE\n"
658 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
661 "#ifdef USESPECULAR\n"
662 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
663 "# ifdef USECOLORMAPPING\n"
664 " gl_FragColor *= tex2;\n"
667 " gl_FragColor += tex2;\n"
669 "# ifdef USEVERTEXTEXTUREBLEND\n"
670 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
675 "#else // !MODE_GENERIC\n"
680 "#ifdef MODE_BLOOMBLUR\n"
681 "varying TexCoord;\n"
682 "#ifdef VERTEX_SHADER\n"
685 " gl_FrontColor = gl_Color;\n"
686 " TexCoord = gl_MultiTexCoord0.xy;\n"
687 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
691 "#ifdef FRAGMENT_SHADER\n"
692 "uniform sampler2D Texture_First;\n"
693 "uniform vec4 BloomBlur_Parameters;\n"
698 " vec2 tc = TexCoord;\n"
699 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
700 " tc += BloomBlur_Parameters.xy;\n"
701 " for (i = 1;i < SAMPLES;i++)\n"
703 " color += texture2D(Texture_First, tc).rgb;\n"
704 " tc += BloomBlur_Parameters.xy;\n"
706 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
709 "#else // !MODE_BLOOMBLUR\n"
710 "#ifdef MODE_REFRACTION\n"
711 "varying vec2 TexCoord;\n"
712 "varying vec4 ModelViewProjectionPosition;\n"
713 "uniform mat4 TexMatrix;\n"
714 "#ifdef VERTEX_SHADER\n"
718 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
719 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
720 " ModelViewProjectionPosition = gl_Position;\n"
724 "#ifdef FRAGMENT_SHADER\n"
725 "uniform sampler2D Texture_Normal;\n"
726 "uniform sampler2D Texture_Refraction;\n"
727 "uniform sampler2D Texture_Reflection;\n"
729 "uniform vec4 DistortScaleRefractReflect;\n"
730 "uniform vec4 ScreenScaleRefractReflect;\n"
731 "uniform vec4 ScreenCenterRefractReflect;\n"
732 "uniform vec4 RefractColor;\n"
733 "uniform vec4 ReflectColor;\n"
734 "uniform float ReflectFactor;\n"
735 "uniform float ReflectOffset;\n"
739 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
740 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
741 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
742 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
743 " // FIXME temporary hack to detect the case that the reflection\n"
744 " // gets blackened at edges due to leaving the area that contains actual\n"
746 " // Remove this 'ack once we have a better way to stop this thing from\n"
748 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
749 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
750 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
751 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
752 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
753 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
756 "#else // !MODE_REFRACTION\n"
761 "#ifdef MODE_WATER\n"
762 "varying vec2 TexCoord;\n"
763 "varying vec3 EyeVector;\n"
764 "varying vec4 ModelViewProjectionPosition;\n"
765 "#ifdef VERTEX_SHADER\n"
766 "uniform vec3 EyePosition;\n"
767 "uniform mat4 TexMatrix;\n"
771 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
772 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
773 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
774 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
775 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
776 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
777 " ModelViewProjectionPosition = gl_Position;\n"
781 "#ifdef FRAGMENT_SHADER\n"
782 "uniform sampler2D Texture_Normal;\n"
783 "uniform sampler2D Texture_Refraction;\n"
784 "uniform sampler2D Texture_Reflection;\n"
786 "uniform vec4 DistortScaleRefractReflect;\n"
787 "uniform vec4 ScreenScaleRefractReflect;\n"
788 "uniform vec4 ScreenCenterRefractReflect;\n"
789 "uniform vec4 RefractColor;\n"
790 "uniform vec4 ReflectColor;\n"
791 "uniform float ReflectFactor;\n"
792 "uniform float ReflectOffset;\n"
796 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
797 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
798 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
799 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
800 " // FIXME temporary hack to detect the case that the reflection\n"
801 " // gets blackened at edges due to leaving the area that contains actual\n"
803 " // Remove this 'ack once we have a better way to stop this thing from\n"
805 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
806 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
807 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
808 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
809 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
810 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
811 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
812 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
813 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
814 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
815 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
816 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
819 "#else // !MODE_WATER\n"
824 "// common definitions between vertex shader and fragment shader:\n"
826 "varying vec2 TexCoord;\n"
827 "#ifdef USEVERTEXTEXTUREBLEND\n"
828 "varying vec2 TexCoord2;\n"
830 "#ifdef USELIGHTMAP\n"
831 "varying vec2 TexCoordLightmap;\n"
834 "#ifdef MODE_LIGHTSOURCE\n"
835 "varying vec3 CubeVector;\n"
838 "#ifdef MODE_LIGHTSOURCE\n"
839 "varying vec3 LightVector;\n"
841 "#if defined(MODE_LIGHTDIRECTION)\n"
842 "varying vec3 LightVector;\n"
845 "#ifdef USEEYEVECTOR\n"
846 "varying vec3 EyeVector;\n"
849 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
852 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
853 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
854 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
855 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
858 "#ifdef USEREFLECTION\n"
859 "varying vec4 ModelViewProjectionPosition;\n"
861 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
862 "uniform vec3 LightPosition;\n"
863 "varying vec4 ModelViewPosition;\n"
866 "#ifdef MODE_LIGHTSOURCE\n"
867 "uniform vec3 LightPosition;\n"
869 "uniform vec3 EyePosition;\n"
870 "#ifdef MODE_LIGHTDIRECTION\n"
871 "uniform vec3 LightDir;\n"
873 "uniform vec4 FogPlane;\n"
879 "// 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"
881 "// fragment shader specific:\n"
882 "#ifdef FRAGMENT_SHADER\n"
884 "uniform sampler2D Texture_Normal;\n"
885 "uniform sampler2D Texture_Color;\n"
886 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
887 "uniform sampler2D Texture_Gloss;\n"
890 "uniform sampler2D Texture_Glow;\n"
892 "#ifdef USEVERTEXTEXTUREBLEND\n"
893 "uniform sampler2D Texture_SecondaryNormal;\n"
894 "uniform sampler2D Texture_SecondaryColor;\n"
895 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
896 "uniform sampler2D Texture_SecondaryGloss;\n"
899 "uniform sampler2D Texture_SecondaryGlow;\n"
902 "#ifdef USECOLORMAPPING\n"
903 "uniform sampler2D Texture_Pants;\n"
904 "uniform sampler2D Texture_Shirt;\n"
907 "uniform sampler2D Texture_FogMask;\n"
909 "#ifdef USELIGHTMAP\n"
910 "uniform sampler2D Texture_Lightmap;\n"
912 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
913 "uniform sampler2D Texture_Deluxemap;\n"
915 "#ifdef USEREFLECTION\n"
916 "uniform sampler2D Texture_Reflection;\n"
919 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
920 "uniform sampler2DRect Texture_ScreenDepth;\n"
921 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
923 "#ifdef USEDEFERREDLIGHTMAP\n"
924 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
925 "uniform sampler2DRect Texture_ScreenSpecular;\n"
928 "uniform myhalf3 Color_Pants;\n"
929 "uniform myhalf3 Color_Shirt;\n"
930 "uniform myhalf3 FogColor;\n"
933 "uniform float FogRangeRecip;\n"
934 "uniform float FogPlaneViewDist;\n"
935 "uniform float FogHeightFade;\n"
936 "float FogVertex(void)\n"
938 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
939 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
941 "#ifdef USEFOGOUTSIDE\n"
942 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
944 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
946 " return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
950 "#ifdef USEOFFSETMAPPING\n"
951 "uniform float OffsetMapping_Scale;\n"
952 "vec2 OffsetMapping(vec2 TexCoord)\n"
954 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
955 " // 14 sample relief mapping: linear search and then binary search\n"
956 " // this basically steps forward a small amount repeatedly until it finds\n"
957 " // itself inside solid, then jitters forward and back using decreasing\n"
958 " // amounts to find the impact\n"
959 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
960 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
961 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
962 " vec3 RT = vec3(TexCoord, 1);\n"
963 " OffsetVector *= 0.1;\n"
964 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
965 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
966 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
967 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
968 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
969 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
970 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
971 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
972 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
973 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
974 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
975 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
976 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
977 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
980 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
981 " // this basically moves forward the full distance, and then backs up based\n"
982 " // on height of samples\n"
983 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
984 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
985 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
986 " TexCoord += OffsetVector;\n"
987 " OffsetVector *= 0.333;\n"
988 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
989 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
990 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
991 " return TexCoord;\n"
994 "#endif // USEOFFSETMAPPING\n"
996 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
997 "uniform sampler2D Texture_Attenuation;\n"
998 "uniform samplerCube Texture_Cube;\n"
1000 "#ifdef USESHADOWMAPRECT\n"
1001 "# ifdef USESHADOWSAMPLER\n"
1002 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1004 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1008 "#ifdef USESHADOWMAP2D\n"
1009 "# ifdef USESHADOWSAMPLER\n"
1010 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1012 "uniform sampler2D Texture_ShadowMap2D;\n"
1016 "#ifdef USESHADOWMAPVSDCT\n"
1017 "uniform samplerCube Texture_CubeProjection;\n"
1020 "#ifdef USESHADOWMAPCUBE\n"
1021 "# ifdef USESHADOWSAMPLER\n"
1022 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1024 "uniform samplerCube Texture_ShadowMapCube;\n"
1028 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1029 "uniform vec2 ShadowMap_TextureScale;\n"
1030 "uniform vec4 ShadowMap_Parameters;\n"
1033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1034 "# ifndef USESHADOWMAPVSDCT\n"
1035 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1037 " vec3 adir = abs(dir);\n"
1041 " if (adir.x > adir.y)\n"
1043 " if (adir.x > adir.z) // X\n"
1047 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1053 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1058 " if (adir.y > adir.z) // Y\n"
1062 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1068 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1072 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1073 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1074 " stc.z += ShadowMap_Parameters.z;\n"
1078 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1080 " vec3 adir = abs(dir);\n"
1081 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1082 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1083 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1084 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1085 " stc.z += ShadowMap_Parameters.z;\n"
1089 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1091 "#ifdef USESHADOWMAPCUBE\n"
1092 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1094 " vec3 adir = abs(dir);\n"
1095 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1099 "# ifdef USESHADOWMAPRECT\n"
1100 "float ShadowMapCompare(vec3 dir)\n"
1102 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1104 "# ifdef USESHADOWSAMPLER\n"
1106 "# ifdef USESHADOWMAPPCF\n"
1107 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1108 " 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"
1110 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1115 "# ifdef USESHADOWMAPPCF\n"
1116 "# if USESHADOWMAPPCF > 1\n"
1117 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1118 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1119 " 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"
1120 " 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"
1121 " 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"
1122 " 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"
1123 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1124 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1126 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1127 " vec2 offset = fract(shadowmaptc.xy);\n"
1128 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1129 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1130 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1131 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1132 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1135 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1143 "# ifdef USESHADOWMAP2D\n"
1144 "float ShadowMapCompare(vec3 dir)\n"
1146 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1149 "# ifdef USESHADOWSAMPLER\n"
1150 "# ifdef USESHADOWMAPPCF\n"
1151 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1152 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1153 " 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"
1155 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1158 "# ifdef USESHADOWMAPPCF\n"
1159 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1160 "# ifdef GL_ARB_texture_gather\n"
1161 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1163 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1165 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1166 " center *= ShadowMap_TextureScale;\n"
1167 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1168 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1169 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1170 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1171 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1172 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1173 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1175 "# ifdef GL_EXT_gpu_shader4\n"
1176 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1178 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1180 "# if USESHADOWMAPPCF > 1\n"
1181 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1182 " center *= ShadowMap_TextureScale;\n"
1183 " 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"
1184 " 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"
1185 " 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"
1186 " 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"
1187 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1188 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1190 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1191 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1192 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1193 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1194 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1195 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1199 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1206 "# ifdef USESHADOWMAPCUBE\n"
1207 "float ShadowMapCompare(vec3 dir)\n"
1209 " // apply depth texture cubemap as light filter\n"
1210 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1212 "# ifdef USESHADOWSAMPLER\n"
1213 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1215 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1220 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1221 "#endif // FRAGMENT_SHADER\n"
1226 "#ifdef MODE_DEFERREDGEOMETRY\n"
1227 "#ifdef VERTEX_SHADER\n"
1228 "uniform mat4 TexMatrix;\n"
1229 "#ifdef USEVERTEXTEXTUREBLEND\n"
1230 "uniform mat4 BackgroundTexMatrix;\n"
1232 "uniform mat4 ModelViewMatrix;\n"
1235 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1236 "#ifdef USEVERTEXTEXTUREBLEND\n"
1237 " gl_FrontColor = gl_Color;\n"
1238 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1241 " // transform unnormalized eye direction into tangent space\n"
1242 "#ifdef USEOFFSETMAPPING\n"
1243 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1244 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1245 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1246 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1249 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1250 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1251 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1252 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1254 "#endif // VERTEX_SHADER\n"
1256 "#ifdef FRAGMENT_SHADER\n"
1259 "#ifdef USEOFFSETMAPPING\n"
1260 " // apply offsetmapping\n"
1261 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1262 "#define TexCoord TexCoordOffset\n"
1265 "#ifdef USEALPHAKILL\n"
1266 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1270 "#ifdef USEVERTEXTEXTUREBLEND\n"
1271 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1272 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1273 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1274 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1277 "#ifdef USEVERTEXTEXTUREBLEND\n"
1278 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1280 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1283 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1285 "#endif // FRAGMENT_SHADER\n"
1286 "#else // !MODE_DEFERREDGEOMETRY\n"
1291 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1292 "#ifdef VERTEX_SHADER\n"
1293 "uniform mat4 ModelViewMatrix;\n"
1296 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1297 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1299 "#endif // VERTEX_SHADER\n"
1301 "#ifdef FRAGMENT_SHADER\n"
1302 "uniform mat4 ViewToLight;\n"
1303 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1304 "uniform vec2 ScreenToDepth;\n"
1305 "uniform myhalf3 DeferredColor_Ambient;\n"
1306 "uniform myhalf3 DeferredColor_Diffuse;\n"
1307 "#ifdef USESPECULAR\n"
1308 "uniform myhalf3 DeferredColor_Specular;\n"
1309 "uniform myhalf SpecularPower;\n"
1313 " // calculate viewspace pixel position\n"
1315 " position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1316 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1317 " // decode viewspace pixel normal\n"
1318 " myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1319 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1320 " // surfacenormal = pixel normal in viewspace\n"
1321 " // LightVector = pixel to light in viewspace\n"
1322 " // CubeVector = position in lightspace\n"
1323 " // eyevector = pixel to view in viewspace\n"
1324 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1325 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1326 "#ifdef USEDIFFUSE\n"
1327 " // calculate diffuse shading\n"
1328 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1329 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1331 "#ifdef USESPECULAR\n"
1332 " // calculate directional shading\n"
1333 " vec3 eyevector = position * -1.0;\n"
1334 "# ifdef USEEXACTSPECULARMATH\n"
1335 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1337 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1338 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1342 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1343 " fade *= ShadowMapCompare(CubeVector);\n"
1346 "#ifdef USEDIFFUSE\n"
1347 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1349 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1351 "#ifdef USESPECULAR\n"
1352 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1354 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1357 "# ifdef USECUBEFILTER\n"
1358 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1359 " gl_FragData[0] *= cubecolor;\n"
1360 " gl_FragData[1] *= cubecolor;\n"
1363 "#endif // FRAGMENT_SHADER\n"
1364 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1369 "#ifdef VERTEX_SHADER\n"
1370 "uniform mat4 TexMatrix;\n"
1371 "#ifdef USEVERTEXTEXTUREBLEND\n"
1372 "uniform mat4 BackgroundTexMatrix;\n"
1374 "#ifdef MODE_LIGHTSOURCE\n"
1375 "uniform mat4 ModelToLight;\n"
1379 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1380 " gl_FrontColor = gl_Color;\n"
1382 " // copy the surface texcoord\n"
1383 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1384 "#ifdef USEVERTEXTEXTUREBLEND\n"
1385 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1387 "#ifdef USELIGHTMAP\n"
1388 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1391 "#ifdef MODE_LIGHTSOURCE\n"
1392 " // transform vertex position into light attenuation/cubemap space\n"
1393 " // (-1 to +1 across the light box)\n"
1394 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1396 "# ifdef USEDIFFUSE\n"
1397 " // transform unnormalized light direction into tangent space\n"
1398 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1399 " // normalize it per pixel)\n"
1400 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1401 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1402 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1403 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1407 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1408 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1409 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1410 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1413 " // transform unnormalized eye direction into tangent space\n"
1414 "#ifdef USEEYEVECTOR\n"
1415 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1416 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1417 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1418 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1422 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1423 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1426 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1427 " VectorS = gl_MultiTexCoord1.xyz;\n"
1428 " VectorT = gl_MultiTexCoord2.xyz;\n"
1429 " VectorR = gl_MultiTexCoord3.xyz;\n"
1432 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1433 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1435 "#ifdef USEREFLECTION\n"
1436 " ModelViewProjectionPosition = gl_Position;\n"
1439 "#endif // VERTEX_SHADER\n"
1444 "#ifdef FRAGMENT_SHADER\n"
1445 "#ifdef USEDEFERREDLIGHTMAP\n"
1446 "uniform myhalf3 DeferredMod_Diffuse;\n"
1447 "uniform myhalf3 DeferredMod_Specular;\n"
1449 "uniform myhalf3 Color_Ambient;\n"
1450 "uniform myhalf3 Color_Diffuse;\n"
1451 "uniform myhalf3 Color_Specular;\n"
1452 "uniform myhalf SpecularPower;\n"
1454 "uniform myhalf3 Color_Glow;\n"
1456 "uniform myhalf Alpha;\n"
1457 "#ifdef USEREFLECTION\n"
1458 "uniform vec4 DistortScaleRefractReflect;\n"
1459 "uniform vec4 ScreenScaleRefractReflect;\n"
1460 "uniform vec4 ScreenCenterRefractReflect;\n"
1461 "uniform myhalf4 ReflectColor;\n"
1463 "#ifdef MODE_LIGHTDIRECTION\n"
1464 "uniform myhalf3 LightColor;\n"
1466 "#ifdef MODE_LIGHTSOURCE\n"
1467 "uniform myhalf3 LightColor;\n"
1471 "#ifdef USEOFFSETMAPPING\n"
1472 " // apply offsetmapping\n"
1473 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1474 "#define TexCoord TexCoordOffset\n"
1477 " // combine the diffuse textures (base, pants, shirt)\n"
1478 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1479 "#ifdef USEALPHAKILL\n"
1480 " if (color.a < 0.5)\n"
1483 " color.a *= Alpha;\n"
1484 "#ifdef USECOLORMAPPING\n"
1485 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1487 "#ifdef USEVERTEXTEXTUREBLEND\n"
1488 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1489 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1490 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1491 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1493 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1496 " // get the surface normal\n"
1497 "#ifdef USEVERTEXTEXTUREBLEND\n"
1498 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1500 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1503 " // get the material colors\n"
1504 " myhalf3 diffusetex = color.rgb;\n"
1505 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1506 "# ifdef USEVERTEXTEXTUREBLEND\n"
1507 " myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1509 " myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1516 "#ifdef MODE_LIGHTSOURCE\n"
1517 " // light source\n"
1518 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1519 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1520 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1521 "#ifdef USESPECULAR\n"
1522 "#ifdef USEEXACTSPECULARMATH\n"
1523 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1525 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1526 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1528 " color.rgb += glosstex * (specular * Color_Specular);\n"
1530 " color.rgb *= LightColor;\n"
1531 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1532 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1533 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1535 "# ifdef USECUBEFILTER\n"
1536 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1538 "#endif // MODE_LIGHTSOURCE\n"
1543 "#ifdef MODE_LIGHTDIRECTION\n"
1545 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1546 "#define lightcolor LightColor\n"
1547 "#endif // MODE_LIGHTDIRECTION\n"
1548 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1550 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1551 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1552 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1553 " // convert modelspace light vector to tangentspace\n"
1554 " myhalf3 lightnormal;\n"
1555 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1556 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1557 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1558 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1559 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1560 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1561 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1562 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1563 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1564 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1565 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1566 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1567 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1568 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1569 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1571 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1572 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1573 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1579 "#ifdef MODE_LIGHTMAP\n"
1580 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1581 "#endif // MODE_LIGHTMAP\n"
1582 "#ifdef MODE_VERTEXCOLOR\n"
1583 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1584 "#endif // MODE_VERTEXCOLOR\n"
1585 "#ifdef MODE_FLATCOLOR\n"
1586 " color.rgb = diffusetex * Color_Ambient;\n"
1587 "#endif // MODE_FLATCOLOR\n"
1593 "# ifdef USEDIFFUSE\n"
1594 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1595 "# ifdef USESPECULAR\n"
1596 "# ifdef USEEXACTSPECULARMATH\n"
1597 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1599 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1600 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1602 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1604 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1607 " color.rgb = diffusetex * Color_Ambient;\n"
1611 "#ifdef USEDEFERREDLIGHTMAP\n"
1612 " color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1613 " color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1617 "#ifdef USEVERTEXTEXTUREBLEND\n"
1618 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1620 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1625 "#ifdef MODE_LIGHTSOURCE\n"
1626 " color.rgb *= myhalf(FogVertex());\n"
1628 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1632 " // 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"
1633 "#ifdef USEREFLECTION\n"
1634 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1635 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1636 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1637 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1638 " // FIXME temporary hack to detect the case that the reflection\n"
1639 " // gets blackened at edges due to leaving the area that contains actual\n"
1641 " // Remove this 'ack once we have a better way to stop this thing from\n"
1643 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1644 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1645 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1646 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1647 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1648 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1651 " gl_FragColor = vec4(color);\n"
1653 "#endif // FRAGMENT_SHADER\n"
1655 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1656 "#endif // !MODE_DEFERREDGEOMETRY\n"
1657 "#endif // !MODE_WATER\n"
1658 "#endif // !MODE_REFRACTION\n"
1659 "#endif // !MODE_BLOOMBLUR\n"
1660 "#endif // !MODE_GENERIC\n"
1661 "#endif // !MODE_POSTPROCESS\n"
1662 "#endif // !MODE_SHOWDEPTH\n"
1663 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1667 =========================================================================================================================================================
1671 =========================================================================================================================================================
1675 =========================================================================================================================================================
1679 =========================================================================================================================================================
1683 =========================================================================================================================================================
1687 =========================================================================================================================================================
1691 =========================================================================================================================================================
1694 const char *builtincgshaderstring =
1695 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1696 "// written by Forest 'LordHavoc' Hale\n"
1697 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1699 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1702 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1703 "#define USELIGHTMAP\n"
1705 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1706 "#define USEEYEVECTOR\n"
1709 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1710 "#ifdef VERTEX_SHADER\n"
1713 "float4 gl_Vertex : POSITION,\n"
1714 "uniform float4x4 ModelViewProjectionMatrix,\n"
1715 "out float4 gl_Position : POSITION\n"
1718 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1721 "#else // !MODE_DEPTH_ORSHADOW\n"
1726 "#ifdef MODE_SHOWDEPTH\n"
1727 "#ifdef VERTEX_SHADER\n"
1730 "float4 gl_Vertex : POSITION,\n"
1731 "uniform float4x4 ModelViewProjectionMatrix,\n"
1732 "out float4 gl_Position : POSITION,\n"
1733 "out float4 gl_FrontColor : COLOR0\n"
1736 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1737 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1741 "#ifdef FRAGMENT_SHADER\n"
1744 "float4 gl_FrontColor : COLOR0,\n"
1745 "out float4 gl_FragColor : COLOR\n"
1748 " gl_FragColor = gl_FrontColor;\n"
1751 "#else // !MODE_SHOWDEPTH\n"
1756 "#ifdef MODE_POSTPROCESS\n"
1758 "#ifdef VERTEX_SHADER\n"
1761 "float4 gl_Vertex : POSITION,\n"
1762 "uniform float4x4 ModelViewProjectionMatrix,\n"
1763 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1764 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1765 "out float4 gl_Position : POSITION,\n"
1766 "out float2 TexCoord1 : TEXCOORD0,\n"
1767 "out float2 TexCoord2 : TEXCOORD1\n"
1770 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1771 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1773 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1778 "#ifdef FRAGMENT_SHADER\n"
1781 "float2 TexCoord1 : TEXCOORD0,\n"
1782 "float2 TexCoord2 : TEXCOORD1,\n"
1783 "uniform sampler2D Texture_First,\n"
1785 "uniform sampler2D Texture_Second,\n"
1787 "#ifdef USEGAMMARAMPS\n"
1788 "uniform sampler2D Texture_GammaRamps,\n"
1790 "#ifdef USESATURATION\n"
1791 "uniform float Saturation,\n"
1793 "#ifdef USEVIEWTINT\n"
1794 "uniform float4 ViewTintColor,\n"
1796 "uniform float4 UserVec1,\n"
1797 "uniform float4 UserVec2,\n"
1798 "uniform float4 UserVec3,\n"
1799 "uniform float4 UserVec4,\n"
1800 "uniform float ClientTime,\n"
1801 "uniform float2 PixelSize,\n"
1802 "out float4 gl_FragColor : COLOR\n"
1805 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1807 " gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1809 "#ifdef USEVIEWTINT\n"
1810 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1813 "#ifdef USEPOSTPROCESSING\n"
1814 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1815 "// 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"
1816 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1817 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1818 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1819 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
1820 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
1821 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1824 "#ifdef USESATURATION\n"
1825 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1826 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1827 " //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1828 " gl_FragColor.rgb = mix(float3(y), gl_FragColor.rgb, Saturation);\n"
1831 "#ifdef USEGAMMARAMPS\n"
1832 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1833 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1834 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1838 "#else // !MODE_POSTPROCESS\n"
1843 "#ifdef MODE_GENERIC\n"
1844 "#ifdef VERTEX_SHADER\n"
1847 "float4 gl_Vertex : POSITION,\n"
1848 "uniform float4x4 ModelViewProjectionMatrix,\n"
1849 "float4 gl_Color : COLOR0,\n"
1850 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1851 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1852 "out float4 gl_Position : POSITION,\n"
1853 "out float4 gl_FrontColor : COLOR,\n"
1854 "out float2 TexCoord1 : TEXCOORD0,\n"
1855 "out float2 TexCoord2 : TEXCOORD1\n"
1858 " gl_FrontColor = gl_Color;\n"
1859 "#ifdef USEDIFFUSE\n"
1860 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1862 "#ifdef USESPECULAR\n"
1863 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1865 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1869 "#ifdef FRAGMENT_SHADER\n"
1873 "float4 gl_FrontColor : COLOR,\n"
1874 "float2 TexCoord1 : TEXCOORD0,\n"
1875 "float2 TexCoord2 : TEXCOORD1,\n"
1876 "#ifdef USEDIFFUSE\n"
1877 "uniform sampler2D Texture_First,\n"
1879 "#ifdef USESPECULAR\n"
1880 "uniform sampler2D Texture_Second,\n"
1882 "out float4 gl_FragColor : COLOR\n"
1885 " gl_FragColor = gl_FrontColor;\n"
1886 "#ifdef USEDIFFUSE\n"
1887 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1890 "#ifdef USESPECULAR\n"
1891 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1892 "# ifdef USECOLORMAPPING\n"
1893 " gl_FragColor *= tex2;\n"
1896 " gl_FragColor += tex2;\n"
1898 "# ifdef USEVERTEXTEXTUREBLEND\n"
1899 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
1904 "#else // !MODE_GENERIC\n"
1909 "#ifdef MODE_BLOOMBLUR\n"
1910 "#ifdef VERTEX_SHADER\n"
1913 "float4 gl_Vertex : POSITION,\n"
1914 "uniform float4x4 ModelViewProjectionMatrix,\n"
1915 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1916 "out float4 gl_Position : POSITION,\n"
1917 "out float2 TexCoord : TEXCOORD0\n"
1920 " TexCoord = gl_MultiTexCoord0.xy;\n"
1921 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1925 "#ifdef FRAGMENT_SHADER\n"
1929 "float2 TexCoord : TEXCOORD0,\n"
1930 "uniform sampler2D Texture_First,\n"
1931 "uniform float4 BloomBlur_Parameters,\n"
1932 "out float4 gl_FragColor : COLOR\n"
1936 " float2 tc = TexCoord;\n"
1937 " float3 color = tex2D(Texture_First, tc).rgb;\n"
1938 " tc += BloomBlur_Parameters.xy;\n"
1939 " for (i = 1;i < SAMPLES;i++)\n"
1941 " color += tex2D(Texture_First, tc).rgb;\n"
1942 " tc += BloomBlur_Parameters.xy;\n"
1944 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1947 "#else // !MODE_BLOOMBLUR\n"
1948 "#ifdef MODE_REFRACTION\n"
1949 "#ifdef VERTEX_SHADER\n"
1952 "float4 gl_Vertex : POSITION,\n"
1953 "uniform float4x4 ModelViewProjectionMatrix,\n"
1954 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1955 "uniform mat4 TexMatrix,\n"
1956 "uniform float3 EyePosition,\n"
1957 "out float4 gl_Position : POSITION,\n"
1958 "out float2 TexCoord : TEXCOORD0,\n"
1959 "out float3 EyeVector : TEXCOORD1,\n"
1960 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1963 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1964 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1965 " ModelViewProjectionPosition = gl_Position;\n"
1969 "#ifdef FRAGMENT_SHADER\n"
1972 "float2 TexCoord : TEXCOORD0,\n"
1973 "float3 EyeVector : TEXCOORD1,\n"
1974 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1975 "uniform sampler2D Texture_Normal,\n"
1976 "uniform sampler2D Texture_Refraction,\n"
1977 "uniform sampler2D Texture_Reflection,\n"
1978 "uniform float4 DistortScaleRefractReflect,\n"
1979 "uniform float4 ScreenScaleRefractReflect,\n"
1980 "uniform float4 ScreenCenterRefractReflect,\n"
1981 "uniform float4 RefractColor,\n"
1982 "out float4 gl_FragColor : COLOR\n"
1985 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1986 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1987 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1988 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1989 " // FIXME temporary hack to detect the case that the reflection\n"
1990 " // gets blackened at edges due to leaving the area that contains actual\n"
1992 " // Remove this 'ack once we have a better way to stop this thing from\n"
1994 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
1995 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
1996 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
1997 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
1998 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1999 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2002 "#else // !MODE_REFRACTION\n"
2007 "#ifdef MODE_WATER\n"
2008 "#ifdef VERTEX_SHADER\n"
2012 "float4 gl_Vertex : POSITION,\n"
2013 "uniform float4x4 ModelViewProjectionMatrix,\n"
2014 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2015 "uniform mat4 TexMatrix,\n"
2016 "uniform float3 EyePosition,\n"
2017 "out float4 gl_Position : POSITION,\n"
2018 "out float2 TexCoord : TEXCOORD0,\n"
2019 "out float3 EyeVector : TEXCOORD1,\n"
2020 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2023 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2024 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2025 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2026 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2027 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2028 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2029 " ModelViewProjectionPosition = gl_Position;\n"
2033 "#ifdef FRAGMENT_SHADER\n"
2036 "float2 TexCoord : TEXCOORD0,\n"
2037 "float3 EyeVector : TEXCOORD1,\n"
2038 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2039 "uniform sampler2D Texture_Normal,\n"
2040 "uniform sampler2D Texture_Refraction,\n"
2041 "uniform sampler2D Texture_Reflection,\n"
2042 "uniform float4 DistortScaleRefractReflect,\n"
2043 "uniform float4 ScreenScaleRefractReflect,\n"
2044 "uniform float4 ScreenCenterRefractReflect,\n"
2045 "uniform float4 RefractColor,\n"
2046 "uniform float4 ReflectColor,\n"
2047 "uniform float ReflectFactor,\n"
2048 "uniform float ReflectOffset,\n"
2049 "out float4 gl_FragColor : COLOR\n"
2052 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2053 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2054 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2055 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2056 " // FIXME temporary hack to detect the case that the reflection\n"
2057 " // gets blackened at edges due to leaving the area that contains actual\n"
2059 " // Remove this 'ack once we have a better way to stop this thing from\n"
2061 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2062 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2063 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2064 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2065 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2066 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2067 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2068 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2069 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2070 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2071 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2072 " gl_FragColor = mix(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2075 "#else // !MODE_WATER\n"
2080 "// 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"
2082 "// fragment shader specific:\n"
2083 "#ifdef FRAGMENT_SHADER\n"
2086 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2089 "#ifdef USEFOGOUTSIDE\n"
2090 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2092 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2094 " return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2098 "#ifdef USEOFFSETMAPPING\n"
2099 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2101 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2102 " // 14 sample relief mapping: linear search and then binary search\n"
2103 " // this basically steps forward a small amount repeatedly until it finds\n"
2104 " // itself inside solid, then jitters forward and back using decreasing\n"
2105 " // amounts to find the impact\n"
2106 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2107 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2108 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2109 " float3 RT = float3(TexCoord, 1);\n"
2110 " OffsetVector *= 0.1;\n"
2111 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2112 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2113 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2114 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2115 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2116 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2117 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2118 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2119 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2120 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2121 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2122 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2123 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2124 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2127 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2128 " // this basically moves forward the full distance, and then backs up based\n"
2129 " // on height of samples\n"
2130 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2131 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2132 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2133 " TexCoord += OffsetVector;\n"
2134 " OffsetVector *= 0.333;\n"
2135 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2136 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2137 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2138 " return TexCoord;\n"
2141 "#endif // USEOFFSETMAPPING\n"
2143 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2144 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2145 "# ifndef USESHADOWMAPVSDCT\n"
2146 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2148 " float3 adir = abs(dir);\n"
2152 " if (adir.x > adir.y)\n"
2154 " if (adir.x > adir.z) // X\n"
2158 " offset = float2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2164 " offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2169 " if (adir.y > adir.z) // Y\n"
2173 " offset = float2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2179 " offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2183 " float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2184 " stc.xy += offset * ShadowMap_Parameters.y;\n"
2185 " stc.z += ShadowMap_Parameters.z;\n"
2189 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2191 " float3 adir = abs(dir);\n"
2192 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2193 " float ma = max(max(adir.x, adir.y), adir.z);\n"
2194 " float3 stc = float3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2195 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2196 " stc.z += ShadowMap_Parameters.z;\n"
2200 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2202 "#ifdef USESHADOWMAPCUBE\n"
2203 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2205 " float3 adir = abs(dir);\n"
2206 " return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2210 "# ifdef USESHADOWMAPRECT\n"
2211 "#ifdef USESHADOWMAPVSDCT\n"
2212 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2214 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2217 "#ifdef USESHADOWMAPVSDCT\n"
2218 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2220 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2223 "# ifdef USESHADOWSAMPLER\n"
2225 "# ifdef USESHADOWMAPPCF\n"
2226 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2227 " f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2229 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2234 "# ifdef USESHADOWMAPPCF\n"
2235 "# if USESHADOWMAPPCF > 1\n"
2236 "# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2237 " float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2238 " float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2239 " float4 row2 = step(shadowmaptc.z, float4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
2240 " float4 row3 = step(shadowmaptc.z, float4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
2241 " float4 row4 = step(shadowmaptc.z, float4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
2242 " float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2243 " f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2245 "# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2246 " float2 offset = fract(shadowmaptc.xy);\n"
2247 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2248 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2249 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2250 " float3 cols = row2 + mix(row1, row3, offset.y);\n"
2251 " f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2254 " f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2262 "# ifdef USESHADOWMAP2D\n"
2263 "#ifdef USESHADOWMAPVSDCT\n"
2264 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2266 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2269 "#ifdef USESHADOWMAPVSDCT\n"
2270 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2272 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2276 "# ifdef USESHADOWSAMPLER\n"
2277 "# ifdef USESHADOWMAPPCF\n"
2278 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
2279 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2280 " f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2282 " f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2285 "# ifdef USESHADOWMAPPCF\n"
2286 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2287 "# ifdef GL_ARB_texture_gather\n"
2288 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2290 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2292 " float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2293 " center *= ShadowMap_TextureScale;\n"
2294 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2295 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2296 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2297 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2298 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2299 " mix(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2300 " f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2302 "# ifdef GL_EXT_gpu_shader4\n"
2303 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, ifloat2(x, y)).r\n"
2305 "# define texval(x, y) tex2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2307 "# if USESHADOWMAPPCF > 1\n"
2308 " float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2309 " center *= ShadowMap_TextureScale;\n"
2310 " float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2311 " float4 row2 = step(shadowmaptc.z, float4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
2312 " float4 row3 = step(shadowmaptc.z, float4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
2313 " float4 row4 = step(shadowmaptc.z, float4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
2314 " float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2315 " f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2317 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
2318 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2319 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2320 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2321 " float3 cols = row2 + mix(row1, row3, offset.y);\n"
2322 " f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2326 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2333 "# ifdef USESHADOWMAPCUBE\n"
2334 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2336 " // apply depth texture cubemap as light filter\n"
2337 " float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2339 "# ifdef USESHADOWSAMPLER\n"
2340 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2342 " f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2347 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2348 "#endif // FRAGMENT_SHADER\n"
2353 "#ifdef MODE_DEFERREDGEOMETRY\n"
2354 "#ifdef VERTEX_SHADER\n"
2357 "float4 gl_Vertex : POSITION,\n"
2358 "uniform float4x4 ModelViewProjectionMatrix,\n"
2359 "#ifdef USEVERTEXTEXTUREBLEND\n"
2360 "float4 gl_Color : COLOR0,\n"
2362 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2363 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2364 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2365 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2366 "uniform mat4 TexMatrix,\n"
2367 "#ifdef USEVERTEXTEXTUREBLEND\n"
2368 "uniform mat4 BackgroundTexMatrix,\n"
2370 "uniform mat4 ModelViewMatrix,\n"
2371 "out float4 gl_Position : POSITION,\n"
2372 "out float4 gl_FrontColor : COLOR,\n"
2373 "out float4 TexCoordBoth : TEXCOORD0,\n"
2374 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2375 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2376 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2379 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2380 "#ifdef USEVERTEXTEXTUREBLEND\n"
2381 " gl_FrontColor = gl_Color;\n"
2382 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2385 " // transform unnormalized eye direction into tangent space\n"
2386 "#ifdef USEOFFSETMAPPING\n"
2387 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2388 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2389 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2390 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2393 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2394 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2395 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2396 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2398 "#endif // VERTEX_SHADER\n"
2400 "#ifdef FRAGMENT_SHADER\n"
2403 "float4 TexCoordBoth : TEXCOORD0,\n"
2404 "float3 EyeVector : TEXCOORD2,\n"
2405 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2406 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2407 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2408 "uniform sampler2D Texture_Normal,\n"
2409 "#ifdef USEALPHAKILL\n"
2410 "uniform sampler2D Texture_Color,\n"
2412 "#ifdef USEVERTEXTEXTUREBLEND\n"
2413 "uniform sampler2D Texture_SecondaryNormal,\n"
2415 "#ifdef USEOFFSETMAPPING\n"
2416 "uniform float OffsetMapping_Scale,\n"
2418 "uniform half SpecularPower,\n"
2419 "out float4 gl_FragColor : COLOR\n"
2422 " float2 TexCoord = TexCoordBoth.xy;\n"
2423 "#ifdef USEOFFSETMAPPING\n"
2424 " // apply offsetmapping\n"
2425 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2426 "#define TexCoord TexCoordOffset\n"
2429 "#ifdef USEALPHAKILL\n"
2430 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2434 "#ifdef USEVERTEXTEXTUREBLEND\n"
2435 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2436 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2437 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2438 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2441 "#ifdef USEVERTEXTEXTUREBLEND\n"
2442 " float3 surfacenormal = mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2444 " float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2447 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2449 "#endif // FRAGMENT_SHADER\n"
2450 "#else // !MODE_DEFERREDGEOMETRY\n"
2455 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2456 "#ifdef VERTEX_SHADER\n"
2459 "float4 gl_Vertex : POSITION,\n"
2460 "uniform float4x4 ModelViewProjectionMatrix,\n"
2461 "uniform mat4 ModelViewMatrix,\n"
2462 "out float4 gl_Position : POSITION,\n"
2463 "out float4 ModelViewPosition : TEXCOORD0\n"
2466 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2467 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2469 "#endif // VERTEX_SHADER\n"
2471 "#ifdef FRAGMENT_SHADER\n"
2474 "float2 Pixel : WPOS,\n"
2475 "float4 ModelViewPosition : TEXCOORD0,\n"
2476 "uniform mat4 ViewToLight,\n"
2477 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2478 "uniform float3 LightPosition,\n"
2479 "uniform half3 DeferredColor_Ambient,\n"
2480 "uniform half3 DeferredColor_Diffuse,\n"
2481 "#ifdef USESPECULAR\n"
2482 "uniform half3 DeferredColor_Specular,\n"
2483 "uniform half SpecularPower,\n"
2485 "uniform sampler2D Texture_Attenuation,\n"
2486 "uniform samplerRECT Texture_ScreenDepth,\n"
2487 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2489 "#ifdef USESHADOWMAPRECT\n"
2490 "# ifdef USESHADOWSAMPLER\n"
2491 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2493 "uniform samplerRECT Texture_ShadowMapRect,\n"
2497 "#ifdef USESHADOWMAP2D\n"
2498 "# ifdef USESHADOWSAMPLER\n"
2499 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2501 "uniform sampler2D Texture_ShadowMap2D,\n"
2505 "#ifdef USESHADOWMAPVSDCT\n"
2506 "uniform samplerCUBE Texture_CubeProjection,\n"
2509 "#ifdef USESHADOWMAPCUBE\n"
2510 "# ifdef USESHADOWSAMPLER\n"
2511 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2513 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2517 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2518 "uniform float2 ShadowMap_TextureScale,\n"
2519 "uniform float4 ShadowMap_Parameters,\n"
2522 "out float4 gl_FragData0 : COLOR0,\n"
2523 "out float4 gl_FragData1 : COLOR1\n"
2526 " // calculate viewspace pixel position\n"
2527 " float3 position;\n"
2528 " position.z = ScreenToDepth.y / (texRECT(Texture_ScreenDepth, Pixel).r + ScreenToDepth.x);\n"
2529 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2530 " // decode viewspace pixel normal\n"
2531 " half4 normalmap = texRECT(Texture_ScreenNormalMap, Pixel);\n"
2532 " half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2533 " // surfacenormal = pixel normal in viewspace\n"
2534 " // LightVector = pixel to light in viewspace\n"
2535 " // CubeVector = position in lightspace\n"
2536 " // eyevector = pixel to view in viewspace\n"
2537 " float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2538 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2539 "#ifdef USEDIFFUSE\n"
2540 " // calculate diffuse shading\n"
2541 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2542 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2544 "#ifdef USESPECULAR\n"
2545 " // calculate directional shading\n"
2546 " float3 eyevector = position * -1.0;\n"
2547 "# ifdef USEEXACTSPECULARMATH\n"
2548 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2550 " half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2551 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2555 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2556 " fade *= ShadowMapCompare(CubeVector,\n"
2557 "# if defined(USESHADOWMAP2D)\n"
2558 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2560 "# if defined(USESHADOWMAPRECT)\n"
2561 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2563 "# if defined(USESHADOWMAPCUBE)\n"
2564 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2567 "#ifdef USESHADOWMAPVSDCT\n"
2568 ", Texture_CubeProjection\n"
2573 "#ifdef USEDIFFUSE\n"
2574 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2576 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2578 "#ifdef USESPECULAR\n"
2579 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2581 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2584 "# ifdef USECUBEFILTER\n"
2585 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2586 " gl_FragData0 *= cubecolor;\n"
2587 " gl_FragData1 *= cubecolor;\n"
2590 "#endif // FRAGMENT_SHADER\n"
2591 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2596 "#ifdef VERTEX_SHADER\n"
2599 "float4 gl_Vertex : POSITION,\n"
2600 "uniform float4x4 ModelViewProjectionMatrix,\n"
2601 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2602 "float4 gl_Color : COLOR0,\n"
2604 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2605 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2606 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2607 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2608 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2610 "uniform float3 EyePosition,\n"
2611 "uniform mat4 TexMatrix,\n"
2612 "#ifdef USEVERTEXTEXTUREBLEND\n"
2613 "uniform mat4 BackgroundTexMatrix,\n"
2615 "#ifdef MODE_LIGHTSOURCE\n"
2616 "uniform mat4 ModelToLight,\n"
2618 "#ifdef MODE_LIGHTSOURCE\n"
2619 "uniform float3 LightPosition,\n"
2621 "#ifdef MODE_LIGHTDIRECTION\n"
2622 "uniform float3 LightDir,\n"
2624 "uniform float4 FogPlane,\n"
2625 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2626 "uniform float3 LightPosition,\n"
2629 "out float4 gl_FrontColor : COLOR,\n"
2630 "out float4 TexCoordBoth : TEXCOORD0,\n"
2631 "#ifdef USELIGHTMAP\n"
2632 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2634 "#ifdef USEEYEVECTOR\n"
2635 "out float3 EyeVector : TEXCOORD2,\n"
2637 "#ifdef USEREFLECTION\n"
2638 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2641 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2643 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2644 "out float3 LightVector : TEXCOORD5,\n"
2646 "#ifdef MODE_LIGHTSOURCE\n"
2647 "out float3 CubeVector : TEXCOORD3,\n"
2649 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2650 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2651 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2652 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2654 "out float4 gl_Position : POSITION\n"
2657 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2658 " gl_FrontColor = gl_Color;\n"
2660 " // copy the surface texcoord\n"
2661 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2662 "#ifdef USEVERTEXTEXTUREBLEND\n"
2663 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2665 "#ifdef USELIGHTMAP\n"
2666 " TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2669 "#ifdef MODE_LIGHTSOURCE\n"
2670 " // transform vertex position into light attenuation/cubemap space\n"
2671 " // (-1 to +1 across the light box)\n"
2672 " CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2674 "# ifdef USEDIFFUSE\n"
2675 " // transform unnormalized light direction into tangent space\n"
2676 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2677 " // normalize it per pixel)\n"
2678 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2679 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2680 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2681 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2685 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2686 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2687 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2688 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2691 " // transform unnormalized eye direction into tangent space\n"
2692 "#ifdef USEEYEVECTOR\n"
2693 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2694 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2695 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2696 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2700 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2701 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2704 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2705 " VectorS = gl_MultiTexCoord1.xyz;\n"
2706 " VectorT = gl_MultiTexCoord2.xyz;\n"
2707 " VectorR = gl_MultiTexCoord3.xyz;\n"
2710 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2711 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2713 "#ifdef USEREFLECTION\n"
2714 " ModelViewProjectionPosition = gl_Position;\n"
2717 "#endif // VERTEX_SHADER\n"
2722 "#ifdef FRAGMENT_SHADER\n"
2725 "#ifdef USEDEFERREDLIGHTMAP\n"
2726 "float2 Pixel : WPOS,\n"
2728 "float4 gl_FrontColor : COLOR,\n"
2729 "float4 TexCoordBoth : TEXCOORD0,\n"
2730 "#ifdef USELIGHTMAP\n"
2731 "float2 TexCoordLightmap : TEXCOORD1,\n"
2733 "#ifdef USEEYEVECTOR\n"
2734 "float3 EyeVector : TEXCOORD2,\n"
2736 "#ifdef USEREFLECTION\n"
2737 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2740 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2742 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2743 "float3 LightVector : TEXCOORD5,\n"
2745 "#ifdef MODE_LIGHTSOURCE\n"
2746 "float3 CubeVector : TEXCOORD3,\n"
2748 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2749 "float4 ModelViewPosition : TEXCOORD0,\n"
2751 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2752 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2753 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2754 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2757 "uniform sampler2D Texture_Normal,\n"
2758 "uniform sampler2D Texture_Color,\n"
2759 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2760 "uniform sampler2D Texture_Gloss,\n"
2763 "uniform sampler2D Texture_Glow,\n"
2765 "#ifdef USEVERTEXTEXTUREBLEND\n"
2766 "uniform sampler2D Texture_SecondaryNormal,\n"
2767 "uniform sampler2D Texture_SecondaryColor,\n"
2768 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2769 "uniform sampler2D Texture_SecondaryGloss,\n"
2772 "uniform sampler2D Texture_SecondaryGlow,\n"
2775 "#ifdef USECOLORMAPPING\n"
2776 "uniform sampler2D Texture_Pants,\n"
2777 "uniform sampler2D Texture_Shirt,\n"
2780 "uniform sampler2D Texture_FogMask,\n"
2782 "#ifdef USELIGHTMAP\n"
2783 "uniform sampler2D Texture_Lightmap,\n"
2785 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2786 "uniform sampler2D Texture_Deluxemap,\n"
2788 "#ifdef USEREFLECTION\n"
2789 "uniform sampler2D Texture_Reflection,\n"
2792 "//#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2793 "uniform samplerRECT Texture_ScreenDepth,\n"
2794 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2796 "#ifdef USEDEFERREDLIGHTMAP\n"
2797 "uniform samplerRECT Texture_ScreenDiffuse,\n"
2798 "uniform samplerRECT Texture_ScreenSpecular,\n"
2801 "#ifdef USECOLORMAPPING\n"
2802 "uniform half3 Color_Pants,\n"
2803 "uniform half3 Color_Shirt,\n"
2806 "uniform float3 FogColor,\n"
2807 "uniform float FogRangeRecip,\n"
2808 "uniform float FogPlaneViewDist,\n"
2809 "uniform float FogHeightFade,\n"
2812 "#ifdef USEOFFSETMAPPING\n"
2813 "uniform float OffsetMapping_Scale,\n"
2816 "#ifdef USEDEFERREDLIGHTMAP\n"
2817 "uniform half3 DeferredMod_Diffuse,\n"
2818 "uniform half3 DeferredMod_Specular,\n"
2820 "uniform half3 Color_Ambient,\n"
2821 "uniform half3 Color_Diffuse,\n"
2822 "uniform half3 Color_Specular,\n"
2823 "uniform half SpecularPower,\n"
2825 "uniform half3 Color_Glow,\n"
2827 "uniform half Alpha,\n"
2828 "#ifdef USEREFLECTION\n"
2829 "uniform float4 DistortScaleRefractReflect,\n"
2830 "uniform float4 ScreenScaleRefractReflect,\n"
2831 "uniform float4 ScreenCenterRefractReflect,\n"
2832 "uniform half4 ReflectColor,\n"
2834 "#ifdef MODE_LIGHTDIRECTION\n"
2835 "uniform half3 LightColor,\n"
2837 "#ifdef MODE_LIGHTSOURCE\n"
2838 "uniform half3 LightColor,\n"
2841 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2842 "uniform sampler2D Texture_Attenuation,\n"
2843 "uniform samplerCUBE Texture_Cube,\n"
2845 "#ifdef USESHADOWMAPRECT\n"
2846 "# ifdef USESHADOWSAMPLER\n"
2847 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2849 "uniform samplerRECT Texture_ShadowMapRect,\n"
2853 "#ifdef USESHADOWMAP2D\n"
2854 "# ifdef USESHADOWSAMPLER\n"
2855 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2857 "uniform sampler2D Texture_ShadowMap2D,\n"
2861 "#ifdef USESHADOWMAPVSDCT\n"
2862 "uniform samplerCUBE Texture_CubeProjection,\n"
2865 "#ifdef USESHADOWMAPCUBE\n"
2866 "# ifdef USESHADOWSAMPLER\n"
2867 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2869 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2873 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2874 "uniform float2 ShadowMap_TextureScale,\n"
2875 "uniform float4 ShadowMap_Parameters,\n"
2877 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2879 "out float4 gl_FragColor : COLOR\n"
2882 " float2 TexCoord = TexCoordBoth.xy;\n"
2883 "#ifdef USEVERTEXTEXTUREBLEND\n"
2884 " float2 TexCoord2 = TexCoordBoth.zw;\n"
2886 "#ifdef USEOFFSETMAPPING\n"
2887 " // apply offsetmapping\n"
2888 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2889 "#define TexCoord TexCoordOffset\n"
2892 " // combine the diffuse textures (base, pants, shirt)\n"
2893 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2894 "#ifdef USEALPHAKILL\n"
2895 " if (color.a < 0.5)\n"
2898 " color.a *= Alpha;\n"
2899 "#ifdef USECOLORMAPPING\n"
2900 " color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2902 "#ifdef USEVERTEXTEXTUREBLEND\n"
2903 " float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2904 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2905 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2906 " color.rgb = half3(mix(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2908 " //color = mix(half4(1, 0, 0, 1), color, terrainblend);\n"
2911 " // get the surface normal\n"
2912 "#ifdef USEVERTEXTEXTUREBLEND\n"
2913 " half3 surfacenormal = normalize(half3(mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2915 " half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2918 " // get the material colors\n"
2919 " half3 diffusetex = color.rgb;\n"
2920 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2921 "# ifdef USEVERTEXTEXTUREBLEND\n"
2922 " half3 glosstex = half3(mix(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2924 " half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2931 "#ifdef MODE_LIGHTSOURCE\n"
2932 " // light source\n"
2933 " half3 lightnormal = half3(normalize(LightVector));\n"
2934 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2935 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2936 "#ifdef USESPECULAR\n"
2937 "#ifdef USEEXACTSPECULARMATH\n"
2938 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2940 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2941 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2943 " color.rgb += glosstex * (specular * Color_Specular);\n"
2945 " color.rgb *= LightColor;\n"
2946 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2947 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2948 " color.rgb *= ShadowMapCompare(CubeVector,\n"
2949 "# if defined(USESHADOWMAP2D)\n"
2950 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2952 "# if defined(USESHADOWMAPRECT)\n"
2953 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2955 "# if defined(USESHADOWMAPCUBE)\n"
2956 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2959 "#ifdef USESHADOWMAPVSDCT\n"
2960 ", Texture_CubeProjection\n"
2965 "# ifdef USECUBEFILTER\n"
2966 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2968 "#endif // MODE_LIGHTSOURCE\n"
2973 "#ifdef MODE_LIGHTDIRECTION\n"
2975 " half3 lightnormal = half3(normalize(LightVector));\n"
2976 "#define lightcolor LightColor\n"
2977 "#endif // MODE_LIGHTDIRECTION\n"
2978 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2980 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
2981 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
2982 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
2983 " // convert modelspace light vector to tangentspace\n"
2984 " half3 lightnormal;\n"
2985 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
2986 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
2987 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
2988 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
2989 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
2990 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
2991 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
2992 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
2993 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
2994 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
2995 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
2996 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
2997 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
2998 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2999 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3001 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3002 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3003 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3009 "#ifdef MODE_LIGHTMAP\n"
3010 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3011 "#endif // MODE_LIGHTMAP\n"
3012 "#ifdef MODE_VERTEXCOLOR\n"
3013 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3014 "#endif // MODE_VERTEXCOLOR\n"
3015 "#ifdef MODE_FLATCOLOR\n"
3016 " color.rgb = diffusetex * Color_Ambient;\n"
3017 "#endif // MODE_FLATCOLOR\n"
3023 "# ifdef USEDIFFUSE\n"
3024 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3025 "# ifdef USESPECULAR\n"
3026 "# ifdef USEEXACTSPECULARMATH\n"
3027 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3029 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3030 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3032 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3034 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3037 " color.rgb = diffusetex * Color_Ambient;\n"
3041 "#ifdef USEDEFERREDLIGHTMAP\n"
3042 " color.rgb += diffusetex * half3(texRECT(Texture_ScreenDiffuse, Pixel)) * DeferredMod_Diffuse;\n"
3043 " color.rgb += glosstex * half3(texRECT(Texture_ScreenSpecular, Pixel)) * DeferredMod_Specular;\n"
3044 " color.rgb = half3(texRECT(Texture_ScreenDepth, Pixel));\n"
3048 "#ifdef USEVERTEXTEXTUREBLEND\n"
3049 " color.rgb += mix(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3051 " color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3056 "#ifdef MODE_LIGHTSOURCE\n"
3057 " color.rgb *= half(FogVertex());\n"
3059 " color.rgb = mix(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3063 " // 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"
3064 "#ifdef USEREFLECTION\n"
3065 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3066 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3067 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3068 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3069 " // FIXME temporary hack to detect the case that the reflection\n"
3070 " // gets blackened at edges due to leaving the area that contains actual\n"
3072 " // Remove this 'ack once we have a better way to stop this thing from\n"
3074 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3075 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3076 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3077 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3078 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3079 " color.rgb = mix(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3082 " gl_FragColor = float4(color);\n"
3084 "#endif // FRAGMENT_SHADER\n"
3086 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3087 "#endif // !MODE_DEFERREDGEOMETRY\n"
3088 "#endif // !MODE_WATER\n"
3089 "#endif // !MODE_REFRACTION\n"
3090 "#endif // !MODE_BLOOMBLUR\n"
3091 "#endif // !MODE_GENERIC\n"
3092 "#endif // !MODE_POSTPROCESS\n"
3093 "#endif // !MODE_SHOWDEPTH\n"
3094 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3097 //=======================================================================================================================================================
3099 typedef struct shaderpermutationinfo_s
3101 const char *pretext;
3104 shaderpermutationinfo_t;
3106 typedef struct shadermodeinfo_s
3108 const char *vertexfilename;
3109 const char *geometryfilename;
3110 const char *fragmentfilename;
3111 const char *pretext;
3116 typedef enum shaderpermutation_e
3118 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3119 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3120 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3121 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3122 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3123 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3124 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3125 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3126 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3127 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3128 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3129 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3130 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3131 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3132 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3133 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3134 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3135 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3136 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3137 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3138 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3139 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3140 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3141 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3142 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3143 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3144 SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3145 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3147 shaderpermutation_t;
3149 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3150 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3152 {"#define USEDIFFUSE\n", " diffuse"},
3153 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3154 {"#define USEVIEWTINT\n", " viewtint"},
3155 {"#define USECOLORMAPPING\n", " colormapping"},
3156 {"#define USESATURATION\n", " saturation"},
3157 {"#define USEFOGINSIDE\n", " foginside"},
3158 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3159 {"#define USEGAMMARAMPS\n", " gammaramps"},
3160 {"#define USECUBEFILTER\n", " cubefilter"},
3161 {"#define USEGLOW\n", " glow"},
3162 {"#define USEBLOOM\n", " bloom"},
3163 {"#define USESPECULAR\n", " specular"},
3164 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3165 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3166 {"#define USEREFLECTION\n", " reflection"},
3167 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3168 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3169 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3170 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3171 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3172 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3173 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3174 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3175 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3176 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3177 {"#define USEALPHAKILL\n", " alphakill"},
3180 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3181 typedef enum shadermode_e
3183 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3184 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3185 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3186 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3187 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3188 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3189 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3190 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3191 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3192 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3193 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3194 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3195 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3196 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3197 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3202 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3203 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3205 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3206 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3207 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3208 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3209 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3210 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3211 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3212 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3213 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3214 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3215 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3216 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3217 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3218 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3219 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3223 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3225 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3226 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3227 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3228 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3229 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3230 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3231 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3232 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3233 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3234 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3235 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3236 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3237 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3238 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3239 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3243 struct r_glsl_permutation_s;
3244 typedef struct r_glsl_permutation_s
3246 /// hash lookup data
3247 struct r_glsl_permutation_s *hashnext;
3249 unsigned int permutation;
3251 /// indicates if we have tried compiling this permutation already
3253 /// 0 if compilation failed
3255 /// locations of detected uniforms in program object, or -1 if not found
3256 int loc_Texture_First;
3257 int loc_Texture_Second;
3258 int loc_Texture_GammaRamps;
3259 int loc_Texture_Normal;
3260 int loc_Texture_Color;
3261 int loc_Texture_Gloss;
3262 int loc_Texture_Glow;
3263 int loc_Texture_SecondaryNormal;
3264 int loc_Texture_SecondaryColor;
3265 int loc_Texture_SecondaryGloss;
3266 int loc_Texture_SecondaryGlow;
3267 int loc_Texture_Pants;
3268 int loc_Texture_Shirt;
3269 int loc_Texture_FogMask;
3270 int loc_Texture_Lightmap;
3271 int loc_Texture_Deluxemap;
3272 int loc_Texture_Attenuation;
3273 int loc_Texture_Cube;
3274 int loc_Texture_Refraction;
3275 int loc_Texture_Reflection;
3276 int loc_Texture_ShadowMapRect;
3277 int loc_Texture_ShadowMapCube;
3278 int loc_Texture_ShadowMap2D;
3279 int loc_Texture_CubeProjection;
3280 int loc_Texture_ScreenDepth;
3281 int loc_Texture_ScreenNormalMap;
3282 int loc_Texture_ScreenDiffuse;
3283 int loc_Texture_ScreenSpecular;
3285 int loc_BloomBlur_Parameters;
3287 int loc_Color_Ambient;
3288 int loc_Color_Diffuse;
3289 int loc_Color_Specular;
3291 int loc_Color_Pants;
3292 int loc_Color_Shirt;
3293 int loc_DeferredColor_Ambient;
3294 int loc_DeferredColor_Diffuse;
3295 int loc_DeferredColor_Specular;
3296 int loc_DeferredMod_Diffuse;
3297 int loc_DeferredMod_Specular;
3298 int loc_DistortScaleRefractReflect;
3299 int loc_EyePosition;
3301 int loc_FogHeightFade;
3303 int loc_FogPlaneViewDist;
3304 int loc_FogRangeRecip;
3307 int loc_LightPosition;
3308 int loc_OffsetMapping_Scale;
3310 int loc_ReflectColor;
3311 int loc_ReflectFactor;
3312 int loc_ReflectOffset;
3313 int loc_RefractColor;
3315 int loc_ScreenCenterRefractReflect;
3316 int loc_ScreenScaleRefractReflect;
3317 int loc_ScreenToDepth;
3318 int loc_ShadowMap_Parameters;
3319 int loc_ShadowMap_TextureScale;
3320 int loc_SpecularPower;
3325 int loc_ViewTintColor;
3326 int loc_ViewToLight;
3327 int loc_ModelToLight;
3329 int loc_BackgroundTexMatrix;
3330 int loc_ModelViewProjectionMatrix;
3331 int loc_ModelViewMatrix;
3333 r_glsl_permutation_t;
3335 #define SHADERPERMUTATION_HASHSIZE 256
3337 /// information about each possible shader permutation
3338 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3339 /// currently selected permutation
3340 r_glsl_permutation_t *r_glsl_permutation;
3341 /// storage for permutations linked in the hash table
3342 memexpandablearray_t r_glsl_permutationarray;
3344 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3346 //unsigned int hashdepth = 0;
3347 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3348 r_glsl_permutation_t *p;
3349 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3351 if (p->mode == mode && p->permutation == permutation)
3353 //if (hashdepth > 10)
3354 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3359 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3361 p->permutation = permutation;
3362 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3363 r_glsl_permutationhash[mode][hashindex] = p;
3364 //if (hashdepth > 10)
3365 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3369 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3372 if (!filename || !filename[0])
3374 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3377 if (printfromdisknotice)
3378 Con_DPrintf("from disk %s... ", filename);
3379 return shaderstring;
3381 else if (!strcmp(filename, "glsl/default.glsl"))
3383 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3384 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3386 return shaderstring;
3389 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3392 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3393 int vertstrings_count = 0;
3394 int geomstrings_count = 0;
3395 int fragstrings_count = 0;
3396 char *vertexstring, *geometrystring, *fragmentstring;
3397 const char *vertstrings_list[32+3];
3398 const char *geomstrings_list[32+3];
3399 const char *fragstrings_list[32+3];
3400 char permutationname[256];
3407 permutationname[0] = 0;
3408 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3409 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3410 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3412 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3414 // the first pretext is which type of shader to compile as
3415 // (later these will all be bound together as a program object)
3416 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3417 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3418 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3420 // the second pretext is the mode (for example a light source)
3421 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3422 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3423 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3424 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3426 // now add all the permutation pretexts
3427 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3429 if (permutation & (1<<i))
3431 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3432 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3433 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3434 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3438 // keep line numbers correct
3439 vertstrings_list[vertstrings_count++] = "\n";
3440 geomstrings_list[geomstrings_count++] = "\n";
3441 fragstrings_list[fragstrings_count++] = "\n";
3445 // now append the shader text itself
3446 vertstrings_list[vertstrings_count++] = vertexstring;
3447 geomstrings_list[geomstrings_count++] = geometrystring;
3448 fragstrings_list[fragstrings_count++] = fragmentstring;
3450 // if any sources were NULL, clear the respective list
3452 vertstrings_count = 0;
3453 if (!geometrystring)
3454 geomstrings_count = 0;
3455 if (!fragmentstring)
3456 fragstrings_count = 0;
3458 // compile the shader program
3459 if (vertstrings_count + geomstrings_count + fragstrings_count)
3460 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3464 qglUseProgramObjectARB(p->program);CHECKGLERROR
3465 // look up all the uniform variable names we care about, so we don't
3466 // have to look them up every time we set them
3468 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3469 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3470 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3471 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3472 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3473 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3474 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3475 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3476 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3477 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3478 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3479 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3480 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3481 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3482 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3483 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3484 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3485 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3486 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3487 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3488 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3489 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3490 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3491 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3492 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3493 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3494 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3495 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3496 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3497 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3498 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3499 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3500 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3501 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3502 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3503 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3504 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3505 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3506 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3507 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3508 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3509 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3510 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3511 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3512 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3513 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3514 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3515 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3516 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3517 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3518 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3519 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3520 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3521 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3522 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3523 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3524 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3525 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3526 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3527 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3528 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3529 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3530 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3531 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3532 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3533 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3534 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3535 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3536 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3537 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3538 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3539 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3540 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3541 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3542 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3543 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3544 // initialize the samplers to refer to the texture units we use
3545 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3546 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3547 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3548 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3549 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3550 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3551 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3552 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3553 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3554 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3555 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3556 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3557 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3558 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3559 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3560 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3561 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3562 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3563 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3564 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3565 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
3566 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
3567 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3568 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3569 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3570 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3571 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3572 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3574 if (developer.integer)
3575 Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
3578 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3582 Mem_Free(vertexstring);
3584 Mem_Free(geometrystring);
3586 Mem_Free(fragmentstring);
3589 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3591 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3592 if (r_glsl_permutation != perm)
3594 r_glsl_permutation = perm;
3595 if (!r_glsl_permutation->program)
3597 if (!r_glsl_permutation->compiled)
3598 R_GLSL_CompilePermutation(perm, mode, permutation);
3599 if (!r_glsl_permutation->program)
3601 // remove features until we find a valid permutation
3603 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3605 // reduce i more quickly whenever it would not remove any bits
3606 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3607 if (!(permutation & j))
3610 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3611 if (!r_glsl_permutation->compiled)
3612 R_GLSL_CompilePermutation(perm, mode, permutation);
3613 if (r_glsl_permutation->program)
3616 if (i >= SHADERPERMUTATION_COUNT)
3618 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3619 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3620 qglUseProgramObjectARB(0);CHECKGLERROR
3621 return; // no bit left to clear, entire mode is broken
3626 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3628 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3632 #include <Cg/cgGL.h>
3633 struct r_cg_permutation_s;
3634 typedef struct r_cg_permutation_s
3636 /// hash lookup data
3637 struct r_cg_permutation_s *hashnext;
3639 unsigned int permutation;
3641 /// indicates if we have tried compiling this permutation already
3643 /// 0 if compilation failed
3646 /// locations of detected parameters in programs, or NULL if not found
3647 CGparameter vp_EyePosition;
3648 CGparameter vp_FogPlane;
3649 CGparameter vp_LightDir;
3650 CGparameter vp_LightPosition;
3651 CGparameter vp_ModelToLight;
3652 CGparameter vp_TexMatrix;
3653 CGparameter vp_BackgroundTexMatrix;
3654 CGparameter vp_ModelViewProjectionMatrix;
3655 CGparameter vp_ModelViewMatrix;
3657 CGparameter fp_Texture_First;
3658 CGparameter fp_Texture_Second;
3659 CGparameter fp_Texture_GammaRamps;
3660 CGparameter fp_Texture_Normal;
3661 CGparameter fp_Texture_Color;
3662 CGparameter fp_Texture_Gloss;
3663 CGparameter fp_Texture_Glow;
3664 CGparameter fp_Texture_SecondaryNormal;
3665 CGparameter fp_Texture_SecondaryColor;
3666 CGparameter fp_Texture_SecondaryGloss;
3667 CGparameter fp_Texture_SecondaryGlow;
3668 CGparameter fp_Texture_Pants;
3669 CGparameter fp_Texture_Shirt;
3670 CGparameter fp_Texture_FogMask;
3671 CGparameter fp_Texture_Lightmap;
3672 CGparameter fp_Texture_Deluxemap;
3673 CGparameter fp_Texture_Attenuation;
3674 CGparameter fp_Texture_Cube;
3675 CGparameter fp_Texture_Refraction;
3676 CGparameter fp_Texture_Reflection;
3677 CGparameter fp_Texture_ShadowMapRect;
3678 CGparameter fp_Texture_ShadowMapCube;
3679 CGparameter fp_Texture_ShadowMap2D;
3680 CGparameter fp_Texture_CubeProjection;
3681 CGparameter fp_Texture_ScreenDepth;
3682 CGparameter fp_Texture_ScreenNormalMap;
3683 CGparameter fp_Texture_ScreenDiffuse;
3684 CGparameter fp_Texture_ScreenSpecular;
3685 CGparameter fp_Alpha;
3686 CGparameter fp_BloomBlur_Parameters;
3687 CGparameter fp_ClientTime;
3688 CGparameter fp_Color_Ambient;
3689 CGparameter fp_Color_Diffuse;
3690 CGparameter fp_Color_Specular;
3691 CGparameter fp_Color_Glow;
3692 CGparameter fp_Color_Pants;
3693 CGparameter fp_Color_Shirt;
3694 CGparameter fp_DeferredColor_Ambient;
3695 CGparameter fp_DeferredColor_Diffuse;
3696 CGparameter fp_DeferredColor_Specular;
3697 CGparameter fp_DeferredMod_Diffuse;
3698 CGparameter fp_DeferredMod_Specular;
3699 CGparameter fp_DistortScaleRefractReflect;
3700 CGparameter fp_EyePosition;
3701 CGparameter fp_FogColor;
3702 CGparameter fp_FogHeightFade;
3703 CGparameter fp_FogPlane;
3704 CGparameter fp_FogPlaneViewDist;
3705 CGparameter fp_FogRangeRecip;
3706 CGparameter fp_LightColor;
3707 CGparameter fp_LightDir;
3708 CGparameter fp_LightPosition;
3709 CGparameter fp_OffsetMapping_Scale;
3710 CGparameter fp_PixelSize;
3711 CGparameter fp_ReflectColor;
3712 CGparameter fp_ReflectFactor;
3713 CGparameter fp_ReflectOffset;
3714 CGparameter fp_RefractColor;
3715 CGparameter fp_Saturation;
3716 CGparameter fp_ScreenCenterRefractReflect;
3717 CGparameter fp_ScreenScaleRefractReflect;
3718 CGparameter fp_ScreenToDepth;
3719 CGparameter fp_ShadowMap_Parameters;
3720 CGparameter fp_ShadowMap_TextureScale;
3721 CGparameter fp_SpecularPower;
3722 CGparameter fp_UserVec1;
3723 CGparameter fp_UserVec2;
3724 CGparameter fp_UserVec3;
3725 CGparameter fp_UserVec4;
3726 CGparameter fp_ViewTintColor;
3727 CGparameter fp_ViewToLight;
3731 /// information about each possible shader permutation
3732 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3733 /// currently selected permutation
3734 r_cg_permutation_t *r_cg_permutation;
3735 /// storage for permutations linked in the hash table
3736 memexpandablearray_t r_cg_permutationarray;
3738 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
3740 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3742 //unsigned int hashdepth = 0;
3743 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3744 r_cg_permutation_t *p;
3745 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3747 if (p->mode == mode && p->permutation == permutation)
3749 //if (hashdepth > 10)
3750 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3755 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3757 p->permutation = permutation;
3758 p->hashnext = r_cg_permutationhash[mode][hashindex];
3759 r_cg_permutationhash[mode][hashindex] = p;
3760 //if (hashdepth > 10)
3761 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3765 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3768 if (!filename || !filename[0])
3770 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3773 if (printfromdisknotice)
3774 Con_DPrintf("from disk %s... ", filename);
3775 return shaderstring;
3777 else if (!strcmp(filename, "cg/default.cg"))
3779 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3780 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3782 return shaderstring;
3785 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3788 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3789 int vertstrings_count = 0, vertstring_length = 0;
3790 int geomstrings_count = 0, geomstring_length = 0;
3791 int fragstrings_count = 0, fragstring_length = 0;
3793 char *vertexstring, *geometrystring, *fragmentstring;
3794 char *vertstring, *geomstring, *fragstring;
3795 const char *vertstrings_list[32+3];
3796 const char *geomstrings_list[32+3];
3797 const char *fragstrings_list[32+3];
3798 char permutationname[256];
3799 CGprofile vertexProfile;
3800 CGprofile fragmentProfile;
3808 permutationname[0] = 0;
3809 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
3810 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3811 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3813 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3815 // the first pretext is which type of shader to compile as
3816 // (later these will all be bound together as a program object)
3817 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3818 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3819 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3821 // the second pretext is the mode (for example a light source)
3822 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3823 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3824 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3825 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3827 // now add all the permutation pretexts
3828 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3830 if (permutation & (1<<i))
3832 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3833 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3834 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3835 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3839 // keep line numbers correct
3840 vertstrings_list[vertstrings_count++] = "\n";
3841 geomstrings_list[geomstrings_count++] = "\n";
3842 fragstrings_list[fragstrings_count++] = "\n";
3846 // now append the shader text itself
3847 vertstrings_list[vertstrings_count++] = vertexstring;
3848 geomstrings_list[geomstrings_count++] = geometrystring;
3849 fragstrings_list[fragstrings_count++] = fragmentstring;
3851 // if any sources were NULL, clear the respective list
3853 vertstrings_count = 0;
3854 if (!geometrystring)
3855 geomstrings_count = 0;
3856 if (!fragmentstring)
3857 fragstrings_count = 0;
3859 vertstring_length = 0;
3860 for (i = 0;i < vertstrings_count;i++)
3861 vertstring_length += strlen(vertstrings_list[i]);
3862 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3863 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3864 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3866 geomstring_length = 0;
3867 for (i = 0;i < geomstrings_count;i++)
3868 geomstring_length += strlen(geomstrings_list[i]);
3869 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3870 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3871 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3873 fragstring_length = 0;
3874 for (i = 0;i < fragstrings_count;i++)
3875 fragstring_length += strlen(fragstrings_list[i]);
3876 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3877 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3878 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3882 //vertexProfile = CG_PROFILE_ARBVP1;
3883 //fragmentProfile = CG_PROFILE_ARBFP1;
3884 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3885 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3886 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3887 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3888 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3891 // compile the vertex program
3892 if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL)))
3895 cgCompileProgram(p->vprogram);CHECKCGERROR
3896 if (!cgIsProgramCompiled(p->vprogram))
3899 cgDestroyProgram(p->vprogram);CHECKCGERROR
3904 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3905 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3906 // look up all the uniform variable names we care about, so we don't
3907 // have to look them up every time we set them
3909 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
3910 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
3911 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
3912 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
3913 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
3914 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
3915 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3916 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3917 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3922 // compile the fragment program
3923 if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL)))
3925 cgCompileProgram(p->fprogram);CHECKCGERROR
3926 if (!cgIsProgramCompiled(p->fprogram))
3929 cgDestroyProgram(p->fprogram);CHECKCGERROR
3934 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3935 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3937 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
3938 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
3939 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3940 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3941 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
3942 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3943 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3944 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3945 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3946 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3947 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3948 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3949 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3950 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3951 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3952 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3953 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3954 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3955 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3956 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3957 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3958 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3959 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3960 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3961 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3962 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3963 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3964 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3965 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
3966 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3967 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
3968 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
3969 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
3970 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
3971 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
3972 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
3973 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
3974 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
3975 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
3976 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
3977 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
3978 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
3979 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
3980 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
3981 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
3982 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
3983 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
3984 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
3985 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
3986 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
3987 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
3988 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
3989 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
3990 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
3991 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
3992 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
3993 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
3994 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
3995 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
3996 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
3997 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
3998 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
3999 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4000 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4001 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4002 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4003 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4004 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4005 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4006 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4007 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4012 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4013 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4015 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4019 Mem_Free(vertstring);
4021 Mem_Free(geomstring);
4023 Mem_Free(fragstring);
4025 Mem_Free(vertexstring);
4027 Mem_Free(geometrystring);
4029 Mem_Free(fragmentstring);
4032 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4034 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4037 if (r_cg_permutation != perm)
4039 r_cg_permutation = perm;
4040 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4042 if (!r_cg_permutation->compiled)
4043 R_CG_CompilePermutation(perm, mode, permutation);
4044 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4046 // remove features until we find a valid permutation
4048 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4050 // reduce i more quickly whenever it would not remove any bits
4051 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4052 if (!(permutation & j))
4055 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4056 if (!r_cg_permutation->compiled)
4057 R_CG_CompilePermutation(perm, mode, permutation);
4058 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4061 if (i >= SHADERPERMUTATION_COUNT)
4063 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4064 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4065 return; // no bit left to clear, entire mode is broken
4071 if (r_cg_permutation->vprogram)
4073 //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4074 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4075 //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4079 //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4080 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4082 if (r_cg_permutation->fprogram)
4084 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4085 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4086 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4090 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4091 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4095 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4098 void CG_BindTexture(CGparameter param, int texnum)
4100 cgGLSetTextureParameter(param, texnum);
4101 cgGLEnableTextureParameter(param);
4105 void R_GLSL_Restart_f(void)
4107 unsigned int i, limit;
4108 switch(vid.renderpath)
4110 case RENDERPATH_GL20:
4112 r_glsl_permutation_t *p;
4113 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4114 for (i = 0;i < limit;i++)
4116 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4118 GL_Backend_FreeProgram(p->program);
4119 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4122 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4125 case RENDERPATH_CGGL:
4128 r_cg_permutation_t *p;
4129 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4130 for (i = 0;i < limit;i++)
4132 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4135 cgDestroyProgram(p->vprogram);
4137 cgDestroyProgram(p->fprogram);
4138 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4142 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4145 case RENDERPATH_GL13:
4146 case RENDERPATH_GL11:
4151 void R_GLSL_DumpShader_f(void)
4156 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4159 FS_Print(file, "/* The engine may define the following macros:\n");
4160 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4161 for (i = 0;i < SHADERMODE_COUNT;i++)
4162 FS_Print(file, glslshadermodeinfo[i].pretext);
4163 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4164 FS_Print(file, shaderpermutationinfo[i].pretext);
4165 FS_Print(file, "*/\n");
4166 FS_Print(file, builtinshaderstring);
4168 Con_Printf("glsl/default.glsl written\n");
4171 Con_Printf("failed to write to glsl/default.glsl\n");
4174 file = FS_OpenRealFile("cg/default.cg", "w", false);
4177 FS_Print(file, "/* The engine may define the following macros:\n");
4178 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4179 for (i = 0;i < SHADERMODE_COUNT;i++)
4180 FS_Print(file, cgshadermodeinfo[i].pretext);
4181 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4182 FS_Print(file, shaderpermutationinfo[i].pretext);
4183 FS_Print(file, "*/\n");
4184 FS_Print(file, builtincgshaderstring);
4186 Con_Printf("cg/default.cg written\n");
4189 Con_Printf("failed to write to cg/default.cg\n");
4193 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4196 texturemode = GL_MODULATE;
4197 switch (vid.renderpath)
4199 case RENDERPATH_GL20:
4200 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4201 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(first ));
4202 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, R_GetTexture(second));
4204 case RENDERPATH_CGGL:
4207 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4208 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , R_GetTexture(first ));CHECKCGERROR
4209 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, R_GetTexture(second));CHECKCGERROR
4212 case RENDERPATH_GL13:
4213 R_Mesh_TexBind(0, R_GetTexture(first ));
4214 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4215 R_Mesh_TexBind(1, R_GetTexture(second));
4217 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4219 case RENDERPATH_GL11:
4220 R_Mesh_TexBind(0, R_GetTexture(first ));
4225 void R_SetupShader_DepthOrShadow(void)
4227 switch (vid.renderpath)
4229 case RENDERPATH_GL20:
4230 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4232 case RENDERPATH_CGGL:
4234 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4237 case RENDERPATH_GL13:
4238 R_Mesh_TexBind(0, 0);
4239 R_Mesh_TexBind(1, 0);
4241 case RENDERPATH_GL11:
4242 R_Mesh_TexBind(0, 0);
4247 void R_SetupShader_ShowDepth(void)
4249 switch (vid.renderpath)
4251 case RENDERPATH_GL20:
4252 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4254 case RENDERPATH_CGGL:
4256 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4259 case RENDERPATH_GL13:
4261 case RENDERPATH_GL11:
4266 extern qboolean r_shadow_usingdeferredprepass;
4267 extern cvar_t r_shadow_deferred_8bitrange;
4268 extern rtexture_t *r_shadow_attenuationgradienttexture;
4269 extern rtexture_t *r_shadow_attenuation2dtexture;
4270 extern rtexture_t *r_shadow_attenuation3dtexture;
4271 extern qboolean r_shadow_usingshadowmaprect;
4272 extern qboolean r_shadow_usingshadowmapcube;
4273 extern qboolean r_shadow_usingshadowmap2d;
4274 extern float r_shadow_shadowmap_texturescale[2];
4275 extern float r_shadow_shadowmap_parameters[4];
4276 extern qboolean r_shadow_shadowmapvsdct;
4277 extern qboolean r_shadow_shadowmapsampler;
4278 extern int r_shadow_shadowmappcf;
4279 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4280 extern rtexture_t *r_shadow_shadowmap2dtexture;
4281 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4282 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4283 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4284 extern int r_shadow_prepass_width;
4285 extern int r_shadow_prepass_height;
4286 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4287 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4288 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4289 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4290 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4292 // select a permutation of the lighting shader appropriate to this
4293 // combination of texture, entity, light source, and fogging, only use the
4294 // minimum features necessary to avoid wasting rendering time in the
4295 // fragment shader on features that are not being used
4296 unsigned int permutation = 0;
4297 unsigned int mode = 0;
4299 // TODO: implement geometry-shader based shadow volumes someday
4300 if (r_glsl_offsetmapping.integer)
4302 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4303 if (r_glsl_offsetmapping_reliefmapping.integer)
4304 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4306 if (rsurfacepass == RSURFPASS_BACKGROUND)
4308 // distorted background
4309 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4310 mode = SHADERMODE_WATER;
4312 mode = SHADERMODE_REFRACTION;
4314 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4316 // normalmap (deferred prepass), may use alpha test on diffuse
4317 mode = SHADERMODE_DEFERREDGEOMETRY;
4318 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4319 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4320 if (r_glsl_offsetmapping.integer)
4322 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4323 if (r_glsl_offsetmapping_reliefmapping.integer)
4324 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4327 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4330 mode = SHADERMODE_LIGHTSOURCE;
4331 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4332 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4333 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4334 permutation |= SHADERPERMUTATION_CUBEFILTER;
4335 if (diffusescale > 0)
4336 permutation |= SHADERPERMUTATION_DIFFUSE;
4337 if (specularscale > 0)
4338 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4339 if (r_refdef.fogenabled)
4340 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4341 if (rsurface.texture->colormapping)
4342 permutation |= SHADERPERMUTATION_COLORMAPPING;
4343 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4345 if (r_shadow_usingshadowmaprect)
4346 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4347 if (r_shadow_usingshadowmap2d)
4348 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4349 if (r_shadow_usingshadowmapcube)
4350 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4351 else if(r_shadow_shadowmapvsdct)
4352 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4354 if (r_shadow_shadowmapsampler)
4355 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4356 if (r_shadow_shadowmappcf > 1)
4357 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4358 else if (r_shadow_shadowmappcf)
4359 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4362 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4364 // unshaded geometry (fullbright or ambient model lighting)
4365 mode = SHADERMODE_FLATCOLOR;
4366 ambientscale = diffusescale = specularscale = 0;
4367 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4368 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4369 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4370 permutation |= SHADERPERMUTATION_GLOW;
4371 if (r_refdef.fogenabled)
4372 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4373 if (rsurface.texture->colormapping)
4374 permutation |= SHADERPERMUTATION_COLORMAPPING;
4375 if (r_glsl_offsetmapping.integer)
4377 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4378 if (r_glsl_offsetmapping_reliefmapping.integer)
4379 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4381 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4382 permutation |= SHADERPERMUTATION_REFLECTION;
4384 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4386 // directional model lighting
4387 mode = SHADERMODE_LIGHTDIRECTION;
4388 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4389 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4390 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4391 permutation |= SHADERPERMUTATION_GLOW;
4392 permutation |= SHADERPERMUTATION_DIFFUSE;
4393 if (specularscale > 0)
4394 permutation |= SHADERPERMUTATION_SPECULAR;
4395 if (r_refdef.fogenabled)
4396 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4397 if (rsurface.texture->colormapping)
4398 permutation |= SHADERPERMUTATION_COLORMAPPING;
4399 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4400 permutation |= SHADERPERMUTATION_REFLECTION;
4401 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4402 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4404 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4406 // ambient model lighting
4407 mode = SHADERMODE_LIGHTDIRECTION;
4408 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4409 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4410 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4411 permutation |= SHADERPERMUTATION_GLOW;
4412 if (r_refdef.fogenabled)
4413 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4414 if (rsurface.texture->colormapping)
4415 permutation |= SHADERPERMUTATION_COLORMAPPING;
4416 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4417 permutation |= SHADERPERMUTATION_REFLECTION;
4418 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4419 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4424 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4426 // deluxemapping (light direction texture)
4427 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4428 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4430 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4431 permutation |= SHADERPERMUTATION_DIFFUSE;
4432 if (specularscale > 0)
4433 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4435 else if (r_glsl_deluxemapping.integer >= 2)
4437 // fake deluxemapping (uniform light direction in tangentspace)
4438 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4439 permutation |= SHADERPERMUTATION_DIFFUSE;
4440 if (specularscale > 0)
4441 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4443 else if (rsurface.uselightmaptexture)
4445 // ordinary lightmapping (q1bsp, q3bsp)
4446 mode = SHADERMODE_LIGHTMAP;
4450 // ordinary vertex coloring (q3bsp)
4451 mode = SHADERMODE_VERTEXCOLOR;
4453 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4454 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4455 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4456 permutation |= SHADERPERMUTATION_GLOW;
4457 if (r_refdef.fogenabled)
4458 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4459 if (rsurface.texture->colormapping)
4460 permutation |= SHADERPERMUTATION_COLORMAPPING;
4461 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4462 permutation |= SHADERPERMUTATION_REFLECTION;
4463 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4464 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4466 if(permutation & SHADERPERMUTATION_SPECULAR)
4467 if(r_shadow_glossexact.integer)
4468 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4469 if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
4470 permutation |= SHADERPERMUTATION_ALPHAKILL;
4471 switch(vid.renderpath)
4473 case RENDERPATH_GL20:
4474 R_SetupShader_SetPermutationGLSL(mode, permutation);
4475 if (mode == SHADERMODE_LIGHTSOURCE)
4477 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4478 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4479 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4480 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);
4481 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);
4482 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
4484 // additive passes are only darkened by fog, not tinted
4485 if (r_glsl_permutation->loc_FogColor >= 0)
4486 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4487 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]);
4488 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]);
4489 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4493 if (mode == SHADERMODE_FLATCOLOR)
4495 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4497 else if (mode == SHADERMODE_LIGHTDIRECTION)
4499 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]);
4500 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
4501 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);
4502 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);
4503 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);
4504 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]);
4505 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]);
4509 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]);
4510 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]);
4511 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);
4512 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);
4513 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);
4515 // additive passes are only darkened by fog, not tinted
4516 if (r_glsl_permutation->loc_FogColor >= 0)
4518 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4519 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4521 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4523 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);
4524 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]);
4525 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]);
4526 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4527 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4528 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4529 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4530 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4532 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4533 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4534 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4535 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4536 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4537 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4538 if (r_glsl_permutation->loc_Color_Pants >= 0)
4540 if (rsurface.texture->pantstexture)
4541 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4543 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4545 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4547 if (rsurface.texture->shirttexture)
4548 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4550 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4552 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]);
4553 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4554 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4555 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4556 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4557 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]);
4559 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(r_texture_white ));
4560 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , R_GetTexture(r_texture_white ));
4561 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , R_GetTexture(r_texture_gammaramps ));
4562 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , R_GetTexture(rsurface.texture->nmaptexture ));
4563 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , R_GetTexture(rsurface.texture->basetexture ));
4564 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , R_GetTexture(rsurface.texture->glosstexture ));
4565 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , R_GetTexture(rsurface.texture->glowtexture ));
4566 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , R_GetTexture(rsurface.texture->backgroundnmaptexture ));
4567 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , R_GetTexture(rsurface.texture->backgroundbasetexture ));
4568 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , R_GetTexture(rsurface.texture->backgroundglosstexture ));
4569 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , R_GetTexture(rsurface.texture->backgroundglowtexture ));
4570 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , R_GetTexture(rsurface.texture->pantstexture ));
4571 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , R_GetTexture(rsurface.texture->shirttexture ));
4572 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , R_GetTexture(r_texture_fogattenuation ));
4573 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(r_texture_white ));
4574 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(r_texture_blanknormalmap ));
4575 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , R_GetTexture(r_shadow_attenuationgradienttexture ));
4576 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , R_GetTexture(r_texture_white ));
4577 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , R_GetTexture(r_texture_white ));
4578 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture ));
4579 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture ));
4580 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture ));
4581 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture ));
4582 if (rsurface.rtlight)
4584 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBindAll(GL20TU_CUBE , 0, 0, R_GetTexture(rsurface.rtlight->currentcubemap ), 0);
4585 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture ));
4586 if (r_shadow_usingshadowmapcube)
4587 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE , 0, 0, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
4588 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , R_GetTexture(r_shadow_shadowmap2dtexture ));
4589 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0, R_GetTexture(r_shadow_shadowmapvsdcttexture ), 0);
4593 case RENDERPATH_CGGL:
4595 R_SetupShader_SetPermutationCG(mode, permutation);
4596 if (mode == SHADERMODE_LIGHTSOURCE)
4598 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4599 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4603 if (mode == SHADERMODE_LIGHTDIRECTION)
4605 if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
4608 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
4609 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4610 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4611 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4612 if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
4615 if (mode == SHADERMODE_LIGHTSOURCE)
4617 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4618 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4619 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);CHECKCGERROR
4620 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);CHECKCGERROR
4621 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, specularscale, specularscale, specularscale);CHECKCGERROR
4623 // additive passes are only darkened by fog, not tinted
4624 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4625 if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
4626 if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
4627 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4631 if (mode == SHADERMODE_FLATCOLOR)
4633 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4635 else if (mode == SHADERMODE_LIGHTDIRECTION)
4637 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_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]);CHECKCGERROR
4638 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);CHECKCGERROR
4639 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);CHECKCGERROR
4640 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_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);CHECKCGERROR
4641 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
4642 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
4643 if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
4647 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);CHECKCGERROR
4648 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
4649 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);CHECKCGERROR
4650 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_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);CHECKCGERROR
4651 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
4653 // additive passes are only darkened by fog, not tinted
4654 if (r_cg_permutation->fp_FogColor)
4656 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4657 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4659 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4662 if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_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);CHECKCGERROR
4663 if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
4664 if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
4665 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4666 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4667 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4668 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4669 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4671 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4672 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4673 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4674 if (r_cg_permutation->fp_Color_Pants)
4676 if (rsurface.texture->pantstexture)
4677 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4679 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4682 if (r_cg_permutation->fp_Color_Shirt)
4684 if (rsurface.texture->shirttexture)
4685 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4687 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4690 if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
4691 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4692 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4693 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4694 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4695 if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
4697 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , R_GetTexture(r_texture_white ));CHECKCGERROR
4698 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , R_GetTexture(r_texture_white ));CHECKCGERROR
4699 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , R_GetTexture(r_texture_gammaramps ));CHECKCGERROR
4700 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , R_GetTexture(rsurface.texture->nmaptexture ));CHECKCGERROR
4701 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , R_GetTexture(rsurface.texture->basetexture ));CHECKCGERROR
4702 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , R_GetTexture(rsurface.texture->glosstexture ));CHECKCGERROR
4703 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , R_GetTexture(rsurface.texture->glowtexture ));CHECKCGERROR
4704 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, R_GetTexture(rsurface.texture->backgroundnmaptexture ));CHECKCGERROR
4705 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , R_GetTexture(rsurface.texture->backgroundbasetexture ));CHECKCGERROR
4706 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , R_GetTexture(rsurface.texture->backgroundglosstexture ));CHECKCGERROR
4707 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , R_GetTexture(rsurface.texture->backgroundglowtexture ));CHECKCGERROR
4708 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , R_GetTexture(rsurface.texture->pantstexture ));CHECKCGERROR
4709 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , R_GetTexture(rsurface.texture->shirttexture ));CHECKCGERROR
4710 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , R_GetTexture(r_texture_fogattenuation ));CHECKCGERROR
4711 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , R_GetTexture(r_texture_white ));CHECKCGERROR
4712 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , R_GetTexture(r_texture_blanknormalmap ));CHECKCGERROR
4713 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , R_GetTexture(r_shadow_attenuationgradienttexture ));CHECKCGERROR
4714 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , R_GetTexture(r_texture_white ));CHECKCGERROR
4715 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , R_GetTexture(r_texture_white ));CHECKCGERROR
4716 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , R_GetTexture(r_shadow_prepassgeometrydepthtexture ));CHECKCGERROR
4717 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture ));CHECKCGERROR
4718 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , R_GetTexture(r_shadow_prepasslightingdiffusetexture ));CHECKCGERROR
4719 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , R_GetTexture(r_shadow_prepasslightingspeculartexture ));CHECKCGERROR
4720 if (rsurface.rtlight)
4722 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , R_GetTexture(rsurface.rtlight->currentcubemap ));CHECKCGERROR
4723 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , R_GetTexture(r_shadow_shadowmaprectangletexture ));CHECKCGERROR
4724 if (r_shadow_usingshadowmapcube)
4725 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));CHECKCGERROR
4726 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , R_GetTexture(r_shadow_shadowmap2dtexture ));CHECKCGERROR
4727 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture ));CHECKCGERROR
4733 case RENDERPATH_GL13:
4734 case RENDERPATH_GL11:
4739 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4741 // select a permutation of the lighting shader appropriate to this
4742 // combination of texture, entity, light source, and fogging, only use the
4743 // minimum features necessary to avoid wasting rendering time in the
4744 // fragment shader on features that are not being used
4745 unsigned int permutation = 0;
4746 unsigned int mode = 0;
4747 const float *lightcolorbase = rtlight->currentcolor;
4748 float ambientscale = rtlight->ambientscale;
4749 float diffusescale = rtlight->diffusescale;
4750 float specularscale = rtlight->specularscale;
4751 // this is the location of the light in view space
4752 vec3_t viewlightorigin;
4753 // this transforms from view space (camera) to light space (cubemap)
4754 matrix4x4_t viewtolight;
4755 matrix4x4_t lighttoview;
4756 float viewtolight16f[16];
4757 float range = 1.0f / r_shadow_deferred_8bitrange.value;
4759 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4760 if (rtlight->currentcubemap != r_texture_whitecube)
4761 permutation |= SHADERPERMUTATION_CUBEFILTER;
4762 if (diffusescale > 0)
4763 permutation |= SHADERPERMUTATION_DIFFUSE;
4764 if (specularscale > 0)
4766 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4767 if (r_shadow_glossexact.integer)
4768 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4770 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4772 if (r_shadow_usingshadowmaprect)
4773 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4774 if (r_shadow_usingshadowmap2d)
4775 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4776 if (r_shadow_usingshadowmapcube)
4777 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4778 else if(r_shadow_shadowmapvsdct)
4779 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4781 if (r_shadow_shadowmapsampler)
4782 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4783 if (r_shadow_shadowmappcf > 1)
4784 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4785 else if (r_shadow_shadowmappcf)
4786 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4788 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4789 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4790 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4791 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4792 switch(vid.renderpath)
4794 case RENDERPATH_GL20:
4795 R_SetupShader_SetPermutationGLSL(mode, permutation);
4796 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix , 1, false, gl_modelview16f);
4797 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4798 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
4799 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);
4800 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);
4801 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);
4802 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]);
4803 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]);
4804 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));
4805 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]);
4807 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , R_GetTexture(r_shadow_attenuationgradienttexture ));
4808 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture ));
4809 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture ));
4810 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBindAll(GL20TU_CUBE , 0, 0, R_GetTexture(rsurface.rtlight->currentcubemap ), 0);
4811 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture ));
4812 if (r_shadow_usingshadowmapcube)
4813 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE , 0, 0, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
4814 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , R_GetTexture(r_shadow_shadowmap2dtexture ));
4815 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0, R_GetTexture(r_shadow_shadowmapvsdcttexture ), 0);
4817 case RENDERPATH_CGGL:
4819 R_SetupShader_SetPermutationCG(mode, permutation);
4820 if (r_cg_permutation->vp_ModelViewMatrix ) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
4821 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4822 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4823 if (r_cg_permutation->fp_DeferredColor_Ambient ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);CHECKCGERROR
4824 if (r_cg_permutation->fp_DeferredColor_Diffuse ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);CHECKCGERROR
4825 if (r_cg_permutation->fp_DeferredColor_Specular ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);CHECKCGERROR
4826 if (r_cg_permutation->fp_ShadowMap_TextureScale ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
4827 if (r_cg_permutation->fp_ShadowMap_Parameters ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
4828 if (r_cg_permutation->fp_SpecularPower ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4829 if (r_cg_permutation->fp_ScreenToDepth ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
4831 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , R_GetTexture(r_shadow_attenuationgradienttexture ));CHECKCGERROR
4832 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , R_GetTexture(r_shadow_prepassgeometrydepthtexture ));CHECKCGERROR
4833 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture ));CHECKCGERROR
4834 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , R_GetTexture(rsurface.rtlight->currentcubemap ));CHECKCGERROR
4835 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , R_GetTexture(r_shadow_shadowmaprectangletexture ));CHECKCGERROR
4836 if (r_shadow_usingshadowmapcube)
4837 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));CHECKCGERROR
4838 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , R_GetTexture(r_shadow_shadowmap2dtexture ));CHECKCGERROR
4839 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture ));CHECKCGERROR
4842 case RENDERPATH_GL13:
4843 case RENDERPATH_GL11:
4848 #define SKINFRAME_HASH 1024
4852 int loadsequence; // incremented each level change
4853 memexpandablearray_t array;
4854 skinframe_t *hash[SKINFRAME_HASH];
4857 r_skinframe_t r_skinframe;
4859 void R_SkinFrame_PrepareForPurge(void)
4861 r_skinframe.loadsequence++;
4862 // wrap it without hitting zero
4863 if (r_skinframe.loadsequence >= 200)
4864 r_skinframe.loadsequence = 1;
4867 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
4871 // mark the skinframe as used for the purging code
4872 skinframe->loadsequence = r_skinframe.loadsequence;
4875 void R_SkinFrame_Purge(void)
4879 for (i = 0;i < SKINFRAME_HASH;i++)
4881 for (s = r_skinframe.hash[i];s;s = s->next)
4883 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
4885 if (s->merged == s->base)
4887 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
4888 R_PurgeTexture(s->stain );s->stain = NULL;
4889 R_PurgeTexture(s->merged);s->merged = NULL;
4890 R_PurgeTexture(s->base );s->base = NULL;
4891 R_PurgeTexture(s->pants );s->pants = NULL;
4892 R_PurgeTexture(s->shirt );s->shirt = NULL;
4893 R_PurgeTexture(s->nmap );s->nmap = NULL;
4894 R_PurgeTexture(s->gloss );s->gloss = NULL;
4895 R_PurgeTexture(s->glow );s->glow = NULL;
4896 R_PurgeTexture(s->fog );s->fog = NULL;
4897 s->loadsequence = 0;
4903 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
4905 char basename[MAX_QPATH];
4907 Image_StripImageExtension(name, basename, sizeof(basename));
4909 if( last == NULL ) {
4911 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4912 item = r_skinframe.hash[hashindex];
4917 // linearly search through the hash bucket
4918 for( ; item ; item = item->next ) {
4919 if( !strcmp( item->basename, basename ) ) {
4926 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
4930 char basename[MAX_QPATH];
4932 Image_StripImageExtension(name, basename, sizeof(basename));
4934 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4935 for (item = r_skinframe.hash[hashindex];item;item = item->next)
4936 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
4940 rtexture_t *dyntexture;
4941 // check whether its a dynamic texture
4942 dyntexture = CL_GetDynTexture( basename );
4943 if (!add && !dyntexture)
4945 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
4946 memset(item, 0, sizeof(*item));
4947 strlcpy(item->basename, basename, sizeof(item->basename));
4948 item->base = dyntexture; // either NULL or dyntexture handle
4949 item->textureflags = textureflags;
4950 item->comparewidth = comparewidth;
4951 item->compareheight = compareheight;
4952 item->comparecrc = comparecrc;
4953 item->next = r_skinframe.hash[hashindex];
4954 r_skinframe.hash[hashindex] = item;
4956 else if( item->base == NULL )
4958 rtexture_t *dyntexture;
4959 // check whether its a dynamic texture
4960 // 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]
4961 dyntexture = CL_GetDynTexture( basename );
4962 item->base = dyntexture; // either NULL or dyntexture handle
4965 R_SkinFrame_MarkUsed(item);
4969 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
4971 unsigned long long avgcolor[5], wsum; \
4979 for(pix = 0; pix < cnt; ++pix) \
4982 for(comp = 0; comp < 3; ++comp) \
4984 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
4987 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4989 for(comp = 0; comp < 3; ++comp) \
4990 avgcolor[comp] += getpixel * w; \
4993 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4994 avgcolor[4] += getpixel; \
4996 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
4998 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
4999 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5000 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5001 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5004 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5007 unsigned char *pixels;
5008 unsigned char *bumppixels;
5009 unsigned char *basepixels = NULL;
5010 int basepixels_width;
5011 int basepixels_height;
5012 skinframe_t *skinframe;
5014 if (cls.state == ca_dedicated)
5017 // return an existing skinframe if already loaded
5018 // if loading of the first image fails, don't make a new skinframe as it
5019 // would cause all future lookups of this to be missing
5020 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5021 if (skinframe && skinframe->base)
5024 basepixels = loadimagepixelsbgra(name, complain, true);
5025 if (basepixels == NULL)
5028 if (developer_loading.integer)
5029 Con_Printf("loading skin \"%s\"\n", name);
5031 // we've got some pixels to store, so really allocate this new texture now
5033 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5034 skinframe->stain = NULL;
5035 skinframe->merged = NULL;
5036 skinframe->base = r_texture_notexture;
5037 skinframe->pants = NULL;
5038 skinframe->shirt = NULL;
5039 skinframe->nmap = r_texture_blanknormalmap;
5040 skinframe->gloss = NULL;
5041 skinframe->glow = NULL;
5042 skinframe->fog = NULL;
5043 skinframe->hasalpha = false;
5045 basepixels_width = image_width;
5046 basepixels_height = image_height;
5047 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);
5049 if (textureflags & TEXF_ALPHA)
5051 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5053 if (basepixels[j] < 255)
5055 skinframe->hasalpha = true;
5059 if (r_loadfog && skinframe->hasalpha)
5061 // has transparent pixels
5062 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5063 for (j = 0;j < image_width * image_height * 4;j += 4)
5068 pixels[j+3] = basepixels[j+3];
5070 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);
5075 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5076 //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]);
5078 // _norm is the name used by tenebrae and has been adopted as standard
5079 if (r_loadnormalmap)
5081 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5083 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);
5087 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5089 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5090 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5091 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);
5093 Mem_Free(bumppixels);
5095 else if (r_shadow_bumpscale_basetexture.value > 0)
5097 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5098 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5099 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);
5103 // _luma is supported for tenebrae compatibility
5104 // (I think it's a very stupid name, but oh well)
5105 // _glow is the preferred name
5106 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;}
5107 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;}
5108 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;}
5109 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;}
5112 Mem_Free(basepixels);
5117 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5118 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5121 unsigned char *temp1, *temp2;
5122 skinframe_t *skinframe;
5124 if (cls.state == ca_dedicated)
5127 // if already loaded just return it, otherwise make a new skinframe
5128 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5129 if (skinframe && skinframe->base)
5132 skinframe->stain = NULL;
5133 skinframe->merged = NULL;
5134 skinframe->base = r_texture_notexture;
5135 skinframe->pants = NULL;
5136 skinframe->shirt = NULL;
5137 skinframe->nmap = r_texture_blanknormalmap;
5138 skinframe->gloss = NULL;
5139 skinframe->glow = NULL;
5140 skinframe->fog = NULL;
5141 skinframe->hasalpha = false;
5143 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5147 if (developer_loading.integer)
5148 Con_Printf("loading 32bit skin \"%s\"\n", name);
5150 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5152 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5153 temp2 = temp1 + width * height * 4;
5154 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5155 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5158 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5159 if (textureflags & TEXF_ALPHA)
5161 for (i = 3;i < width * height * 4;i += 4)
5163 if (skindata[i] < 255)
5165 skinframe->hasalpha = true;
5169 if (r_loadfog && skinframe->hasalpha)
5171 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5172 memcpy(fogpixels, skindata, width * height * 4);
5173 for (i = 0;i < width * height * 4;i += 4)
5174 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5175 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5176 Mem_Free(fogpixels);
5180 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5181 //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]);
5186 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5190 skinframe_t *skinframe;
5192 if (cls.state == ca_dedicated)
5195 // if already loaded just return it, otherwise make a new skinframe
5196 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5197 if (skinframe && skinframe->base)
5200 skinframe->stain = NULL;
5201 skinframe->merged = NULL;
5202 skinframe->base = r_texture_notexture;
5203 skinframe->pants = NULL;
5204 skinframe->shirt = NULL;
5205 skinframe->nmap = r_texture_blanknormalmap;
5206 skinframe->gloss = NULL;
5207 skinframe->glow = NULL;
5208 skinframe->fog = NULL;
5209 skinframe->hasalpha = false;
5211 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5215 if (developer_loading.integer)
5216 Con_Printf("loading quake skin \"%s\"\n", name);
5218 // 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)
5219 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5220 memcpy(skinframe->qpixels, skindata, width*height);
5221 skinframe->qwidth = width;
5222 skinframe->qheight = height;
5225 for (i = 0;i < width * height;i++)
5226 featuresmask |= palette_featureflags[skindata[i]];
5228 skinframe->hasalpha = false;
5229 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5230 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5231 skinframe->qgeneratemerged = true;
5232 skinframe->qgeneratebase = skinframe->qhascolormapping;
5233 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5235 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5236 //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]);
5241 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5245 unsigned char *skindata;
5247 if (!skinframe->qpixels)
5250 if (!skinframe->qhascolormapping)
5251 colormapped = false;
5255 if (!skinframe->qgeneratebase)
5260 if (!skinframe->qgeneratemerged)
5264 width = skinframe->qwidth;
5265 height = skinframe->qheight;
5266 skindata = skinframe->qpixels;
5268 if (skinframe->qgeneratenmap)
5270 unsigned char *temp1, *temp2;
5271 skinframe->qgeneratenmap = false;
5272 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5273 temp2 = temp1 + width * height * 4;
5274 // use either a custom palette or the quake palette
5275 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5276 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5277 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5281 if (skinframe->qgenerateglow)
5283 skinframe->qgenerateglow = false;
5284 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5289 skinframe->qgeneratebase = false;
5290 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);
5291 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5292 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5296 skinframe->qgeneratemerged = false;
5297 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5300 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5302 Mem_Free(skinframe->qpixels);
5303 skinframe->qpixels = NULL;
5307 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)
5310 skinframe_t *skinframe;
5312 if (cls.state == ca_dedicated)
5315 // if already loaded just return it, otherwise make a new skinframe
5316 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5317 if (skinframe && skinframe->base)
5320 skinframe->stain = NULL;
5321 skinframe->merged = NULL;
5322 skinframe->base = r_texture_notexture;
5323 skinframe->pants = NULL;
5324 skinframe->shirt = NULL;
5325 skinframe->nmap = r_texture_blanknormalmap;
5326 skinframe->gloss = NULL;
5327 skinframe->glow = NULL;
5328 skinframe->fog = NULL;
5329 skinframe->hasalpha = false;
5331 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5335 if (developer_loading.integer)
5336 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5338 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5339 if (textureflags & TEXF_ALPHA)
5341 for (i = 0;i < width * height;i++)
5343 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5345 skinframe->hasalpha = true;
5349 if (r_loadfog && skinframe->hasalpha)
5350 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5353 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5354 //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]);
5359 skinframe_t *R_SkinFrame_LoadMissing(void)
5361 skinframe_t *skinframe;
5363 if (cls.state == ca_dedicated)
5366 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5367 skinframe->stain = NULL;
5368 skinframe->merged = NULL;
5369 skinframe->base = r_texture_notexture;
5370 skinframe->pants = NULL;
5371 skinframe->shirt = NULL;
5372 skinframe->nmap = r_texture_blanknormalmap;
5373 skinframe->gloss = NULL;
5374 skinframe->glow = NULL;
5375 skinframe->fog = NULL;
5376 skinframe->hasalpha = false;
5378 skinframe->avgcolor[0] = rand() / RAND_MAX;
5379 skinframe->avgcolor[1] = rand() / RAND_MAX;
5380 skinframe->avgcolor[2] = rand() / RAND_MAX;
5381 skinframe->avgcolor[3] = 1;
5386 void R_Main_FreeViewCache(void)
5388 if (r_refdef.viewcache.entityvisible)
5389 Mem_Free(r_refdef.viewcache.entityvisible);
5390 if (r_refdef.viewcache.world_pvsbits)
5391 Mem_Free(r_refdef.viewcache.world_pvsbits);
5392 if (r_refdef.viewcache.world_leafvisible)
5393 Mem_Free(r_refdef.viewcache.world_leafvisible);
5394 if (r_refdef.viewcache.world_surfacevisible)
5395 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5396 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5399 void R_Main_ResizeViewCache(void)
5401 int numentities = r_refdef.scene.numentities;
5402 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5403 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5404 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5405 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5406 if (r_refdef.viewcache.maxentities < numentities)
5408 r_refdef.viewcache.maxentities = numentities;
5409 if (r_refdef.viewcache.entityvisible)
5410 Mem_Free(r_refdef.viewcache.entityvisible);
5411 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5413 if (r_refdef.viewcache.world_numclusters != numclusters)
5415 r_refdef.viewcache.world_numclusters = numclusters;
5416 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5417 if (r_refdef.viewcache.world_pvsbits)
5418 Mem_Free(r_refdef.viewcache.world_pvsbits);
5419 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5421 if (r_refdef.viewcache.world_numleafs != numleafs)
5423 r_refdef.viewcache.world_numleafs = numleafs;
5424 if (r_refdef.viewcache.world_leafvisible)
5425 Mem_Free(r_refdef.viewcache.world_leafvisible);
5426 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5428 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5430 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5431 if (r_refdef.viewcache.world_surfacevisible)
5432 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5433 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5437 extern rtexture_t *loadingscreentexture;
5438 void gl_main_start(void)
5440 loadingscreentexture = NULL;
5441 r_texture_blanknormalmap = NULL;
5442 r_texture_white = NULL;
5443 r_texture_grey128 = NULL;
5444 r_texture_black = NULL;
5445 r_texture_whitecube = NULL;
5446 r_texture_normalizationcube = NULL;
5447 r_texture_fogattenuation = NULL;
5448 r_texture_gammaramps = NULL;
5450 switch(vid.renderpath)
5452 case RENDERPATH_GL20:
5453 case RENDERPATH_CGGL:
5454 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5455 Cvar_SetValueQuick(&gl_combine, 1);
5456 Cvar_SetValueQuick(&r_glsl, 1);
5457 r_loadnormalmap = true;
5461 case RENDERPATH_GL13:
5462 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5463 Cvar_SetValueQuick(&gl_combine, 1);
5464 Cvar_SetValueQuick(&r_glsl, 0);
5465 r_loadnormalmap = false;
5466 r_loadgloss = false;
5469 case RENDERPATH_GL11:
5470 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5471 Cvar_SetValueQuick(&gl_combine, 0);
5472 Cvar_SetValueQuick(&r_glsl, 0);
5473 r_loadnormalmap = false;
5474 r_loadgloss = false;
5480 R_FrameData_Reset();
5484 memset(r_queries, 0, sizeof(r_queries));
5486 r_qwskincache = NULL;
5487 r_qwskincache_size = 0;
5489 // set up r_skinframe loading system for textures
5490 memset(&r_skinframe, 0, sizeof(r_skinframe));
5491 r_skinframe.loadsequence = 1;
5492 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5494 r_main_texturepool = R_AllocTexturePool();
5495 R_BuildBlankTextures();
5497 if (vid.support.arb_texture_cube_map)
5500 R_BuildNormalizationCube();
5502 r_texture_fogattenuation = NULL;
5503 r_texture_gammaramps = NULL;
5504 //r_texture_fogintensity = NULL;
5505 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5506 memset(&r_waterstate, 0, sizeof(r_waterstate));
5507 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5508 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5510 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5511 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5513 memset(&r_svbsp, 0, sizeof (r_svbsp));
5515 r_refdef.fogmasktable_density = 0;
5518 void gl_main_shutdown(void)
5521 R_FrameData_Reset();
5523 R_Main_FreeViewCache();
5526 qglDeleteQueriesARB(r_maxqueries, r_queries);
5530 memset(r_queries, 0, sizeof(r_queries));
5532 r_qwskincache = NULL;
5533 r_qwskincache_size = 0;
5535 // clear out the r_skinframe state
5536 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5537 memset(&r_skinframe, 0, sizeof(r_skinframe));
5540 Mem_Free(r_svbsp.nodes);
5541 memset(&r_svbsp, 0, sizeof (r_svbsp));
5542 R_FreeTexturePool(&r_main_texturepool);
5543 loadingscreentexture = NULL;
5544 r_texture_blanknormalmap = NULL;
5545 r_texture_white = NULL;
5546 r_texture_grey128 = NULL;
5547 r_texture_black = NULL;
5548 r_texture_whitecube = NULL;
5549 r_texture_normalizationcube = NULL;
5550 r_texture_fogattenuation = NULL;
5551 r_texture_gammaramps = NULL;
5552 //r_texture_fogintensity = NULL;
5553 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5554 memset(&r_waterstate, 0, sizeof(r_waterstate));
5558 extern void CL_ParseEntityLump(char *entitystring);
5559 void gl_main_newmap(void)
5561 // FIXME: move this code to client
5563 char *entities, entname[MAX_QPATH];
5565 Mem_Free(r_qwskincache);
5566 r_qwskincache = NULL;
5567 r_qwskincache_size = 0;
5570 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5571 l = (int)strlen(entname) - 4;
5572 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5574 memcpy(entname + l, ".ent", 5);
5575 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5577 CL_ParseEntityLump(entities);
5582 if (cl.worldmodel->brush.entities)
5583 CL_ParseEntityLump(cl.worldmodel->brush.entities);
5585 R_Main_FreeViewCache();
5587 R_FrameData_Reset();
5590 void GL_Main_Init(void)
5592 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5594 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5595 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5596 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5597 if (gamemode == GAME_NEHAHRA)
5599 Cvar_RegisterVariable (&gl_fogenable);
5600 Cvar_RegisterVariable (&gl_fogdensity);
5601 Cvar_RegisterVariable (&gl_fogred);
5602 Cvar_RegisterVariable (&gl_foggreen);
5603 Cvar_RegisterVariable (&gl_fogblue);
5604 Cvar_RegisterVariable (&gl_fogstart);
5605 Cvar_RegisterVariable (&gl_fogend);
5606 Cvar_RegisterVariable (&gl_skyclip);
5608 Cvar_RegisterVariable(&r_motionblur);
5609 Cvar_RegisterVariable(&r_motionblur_maxblur);
5610 Cvar_RegisterVariable(&r_motionblur_bmin);
5611 Cvar_RegisterVariable(&r_motionblur_vmin);
5612 Cvar_RegisterVariable(&r_motionblur_vmax);
5613 Cvar_RegisterVariable(&r_motionblur_vcoeff);
5614 Cvar_RegisterVariable(&r_motionblur_randomize);
5615 Cvar_RegisterVariable(&r_damageblur);
5616 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5617 Cvar_RegisterVariable(&r_equalize_entities_minambient);
5618 Cvar_RegisterVariable(&r_equalize_entities_by);
5619 Cvar_RegisterVariable(&r_equalize_entities_to);
5620 Cvar_RegisterVariable(&r_depthfirst);
5621 Cvar_RegisterVariable(&r_useinfinitefarclip);
5622 Cvar_RegisterVariable(&r_farclip_base);
5623 Cvar_RegisterVariable(&r_farclip_world);
5624 Cvar_RegisterVariable(&r_nearclip);
5625 Cvar_RegisterVariable(&r_showbboxes);
5626 Cvar_RegisterVariable(&r_showsurfaces);
5627 Cvar_RegisterVariable(&r_showtris);
5628 Cvar_RegisterVariable(&r_shownormals);
5629 Cvar_RegisterVariable(&r_showlighting);
5630 Cvar_RegisterVariable(&r_showshadowvolumes);
5631 Cvar_RegisterVariable(&r_showcollisionbrushes);
5632 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5633 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5634 Cvar_RegisterVariable(&r_showdisabledepthtest);
5635 Cvar_RegisterVariable(&r_drawportals);
5636 Cvar_RegisterVariable(&r_drawentities);
5637 Cvar_RegisterVariable(&r_cullentities_trace);
5638 Cvar_RegisterVariable(&r_cullentities_trace_samples);
5639 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5640 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5641 Cvar_RegisterVariable(&r_cullentities_trace_delay);
5642 Cvar_RegisterVariable(&r_drawviewmodel);
5643 Cvar_RegisterVariable(&r_speeds);
5644 Cvar_RegisterVariable(&r_fullbrights);
5645 Cvar_RegisterVariable(&r_wateralpha);
5646 Cvar_RegisterVariable(&r_dynamic);
5647 Cvar_RegisterVariable(&r_fullbright);
5648 Cvar_RegisterVariable(&r_shadows);
5649 Cvar_RegisterVariable(&r_shadows_darken);
5650 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5651 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5652 Cvar_RegisterVariable(&r_shadows_throwdistance);
5653 Cvar_RegisterVariable(&r_shadows_throwdirection);
5654 Cvar_RegisterVariable(&r_q1bsp_skymasking);
5655 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5656 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5657 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5658 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5659 Cvar_RegisterVariable(&r_fog_exp2);
5660 Cvar_RegisterVariable(&r_drawfog);
5661 Cvar_RegisterVariable(&r_transparentdepthmasking);
5662 Cvar_RegisterVariable(&r_textureunits);
5663 Cvar_RegisterVariable(&gl_combine);
5664 Cvar_RegisterVariable(&r_glsl);
5665 Cvar_RegisterVariable(&r_glsl_deluxemapping);
5666 Cvar_RegisterVariable(&r_glsl_offsetmapping);
5667 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5668 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5669 Cvar_RegisterVariable(&r_glsl_postprocess);
5670 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5671 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5672 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5673 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5674 Cvar_RegisterVariable(&r_water);
5675 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5676 Cvar_RegisterVariable(&r_water_clippingplanebias);
5677 Cvar_RegisterVariable(&r_water_refractdistort);
5678 Cvar_RegisterVariable(&r_water_reflectdistort);
5679 Cvar_RegisterVariable(&r_lerpsprites);
5680 Cvar_RegisterVariable(&r_lerpmodels);
5681 Cvar_RegisterVariable(&r_lerplightstyles);
5682 Cvar_RegisterVariable(&r_waterscroll);
5683 Cvar_RegisterVariable(&r_bloom);
5684 Cvar_RegisterVariable(&r_bloom_colorscale);
5685 Cvar_RegisterVariable(&r_bloom_brighten);
5686 Cvar_RegisterVariable(&r_bloom_blur);
5687 Cvar_RegisterVariable(&r_bloom_resolution);
5688 Cvar_RegisterVariable(&r_bloom_colorexponent);
5689 Cvar_RegisterVariable(&r_bloom_colorsubtract);
5690 Cvar_RegisterVariable(&r_hdr);
5691 Cvar_RegisterVariable(&r_hdr_scenebrightness);
5692 Cvar_RegisterVariable(&r_hdr_glowintensity);
5693 Cvar_RegisterVariable(&r_hdr_range);
5694 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5695 Cvar_RegisterVariable(&developer_texturelogging);
5696 Cvar_RegisterVariable(&gl_lightmaps);
5697 Cvar_RegisterVariable(&r_test);
5698 Cvar_RegisterVariable(&r_batchmode);
5699 Cvar_RegisterVariable(&r_glsl_saturation);
5700 Cvar_RegisterVariable(&r_framedatasize);
5701 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5702 Cvar_SetValue("r_fullbrights", 0);
5703 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5705 Cvar_RegisterVariable(&r_track_sprites);
5706 Cvar_RegisterVariable(&r_track_sprites_flags);
5707 Cvar_RegisterVariable(&r_track_sprites_scalew);
5708 Cvar_RegisterVariable(&r_track_sprites_scaleh);
5711 extern void R_Textures_Init(void);
5712 extern void GL_Draw_Init(void);
5713 extern void GL_Main_Init(void);
5714 extern void R_Shadow_Init(void);
5715 extern void R_Sky_Init(void);
5716 extern void GL_Surf_Init(void);
5717 extern void R_Particles_Init(void);
5718 extern void R_Explosion_Init(void);
5719 extern void gl_backend_init(void);
5720 extern void Sbar_Init(void);
5721 extern void R_LightningBeams_Init(void);
5722 extern void Mod_RenderInit(void);
5723 extern void Font_Init(void);
5725 void Render_Init(void)
5738 R_LightningBeams_Init();
5747 extern char *ENGINE_EXTENSIONS;
5750 gl_renderer = (const char *)qglGetString(GL_RENDERER);
5751 gl_vendor = (const char *)qglGetString(GL_VENDOR);
5752 gl_version = (const char *)qglGetString(GL_VERSION);
5753 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5757 if (!gl_platformextensions)
5758 gl_platformextensions = "";
5760 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5761 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5762 Con_Printf("GL_VERSION: %s\n", gl_version);
5763 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
5764 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
5766 VID_CheckExtensions();
5768 // LordHavoc: report supported extensions
5769 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
5771 // clear to black (loading plaque will be seen over this)
5773 qglClearColor(0,0,0,1);CHECKGLERROR
5774 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
5777 int R_CullBox(const vec3_t mins, const vec3_t maxs)
5781 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5783 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
5786 p = r_refdef.view.frustum + i;
5791 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5795 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5799 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5803 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5807 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5811 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5815 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5819 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5827 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
5831 for (i = 0;i < numplanes;i++)
5838 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5842 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5846 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5850 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5854 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5858 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5862 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5866 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5874 //==================================================================================
5876 // LordHavoc: this stores temporary data used within the same frame
5878 qboolean r_framedata_failed;
5879 static size_t r_framedata_size;
5880 static size_t r_framedata_current;
5881 static void *r_framedata_base;
5883 void R_FrameData_Reset(void)
5885 if (r_framedata_base);
5886 Mem_Free(r_framedata_base);
5887 r_framedata_base = NULL;
5888 r_framedata_size = 0;
5889 r_framedata_current = 0;
5890 r_framedata_failed = false;
5893 void R_FrameData_NewFrame(void)
5896 if (r_framedata_failed)
5897 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
5898 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
5899 wantedsize = bound(65536, wantedsize, 128*1024*1024);
5900 if (r_framedata_size != wantedsize)
5902 r_framedata_size = wantedsize;
5903 if (r_framedata_base);
5904 Mem_Free(r_framedata_base);
5905 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
5907 r_framedata_current = 0;
5908 r_framedata_failed = false;
5911 void *R_FrameData_Alloc(size_t size)
5915 // align to 16 byte boundary
5916 size = (size + 15) & ~15;
5917 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
5918 r_framedata_current += size;
5921 if (r_framedata_current > r_framedata_size)
5922 r_framedata_failed = true;
5924 // return NULL on everything after a failure
5925 if (r_framedata_failed)
5931 void *R_FrameData_Store(size_t size, void *data)
5933 void *d = R_FrameData_Alloc(size);
5935 memcpy(d, data, size);
5939 //==================================================================================
5941 // LordHavoc: animcache originally written by Echon, rewritten since then
5944 * Animation cache prevents re-generating mesh data for an animated model
5945 * multiple times in one frame for lighting, shadowing, reflections, etc.
5948 void R_AnimCache_Free(void)
5952 void R_AnimCache_ClearCache(void)
5955 entity_render_t *ent;
5957 for (i = 0;i < r_refdef.scene.numentities;i++)
5959 ent = r_refdef.scene.entities[i];
5960 ent->animcache_vertex3f = NULL;
5961 ent->animcache_normal3f = NULL;
5962 ent->animcache_svector3f = NULL;
5963 ent->animcache_tvector3f = NULL;
5967 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5969 dp_model_t *model = ent->model;
5971 // see if it's already cached this frame
5972 if (ent->animcache_vertex3f)
5974 // add normals/tangents if needed
5975 if (wantnormals || wanttangents)
5977 if (ent->animcache_normal3f)
5978 wantnormals = false;
5979 if (ent->animcache_svector3f)
5980 wanttangents = false;
5981 if (wantnormals || wanttangents)
5983 numvertices = model->surfmesh.num_vertices;
5985 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
5988 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
5989 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
5991 if (!r_framedata_failed)
5992 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5998 // see if this ent is worth caching
5999 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6001 // get some memory for this entity and generate mesh data
6002 numvertices = model->surfmesh.num_vertices;
6003 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6005 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6008 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6009 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6011 if (!r_framedata_failed)
6012 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6014 return !r_framedata_failed;
6017 void R_AnimCache_CacheVisibleEntities(void)
6020 qboolean wantnormals = !r_showsurfaces.integer;
6021 qboolean wanttangents = !r_showsurfaces.integer;
6023 switch(vid.renderpath)
6025 case RENDERPATH_GL20:
6026 case RENDERPATH_CGGL:
6028 case RENDERPATH_GL13:
6029 case RENDERPATH_GL11:
6030 wanttangents = false;
6034 // TODO: thread this
6035 // NOTE: R_PrepareRTLights() also caches entities
6037 for (i = 0;i < r_refdef.scene.numentities;i++)
6038 if (r_refdef.viewcache.entityvisible[i])
6039 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6041 if (r_shadows.integer)
6042 for (i = 0;i < r_refdef.scene.numentities;i++)
6043 if (!r_refdef.viewcache.entityvisible[i])
6044 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6047 //==================================================================================
6049 static void R_View_UpdateEntityLighting (void)
6052 entity_render_t *ent;
6053 vec3_t tempdiffusenormal, avg;
6054 vec_t f, fa, fd, fdd;
6056 for (i = 0;i < r_refdef.scene.numentities;i++)
6058 ent = r_refdef.scene.entities[i];
6060 // skip unseen models
6061 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6065 if (ent->model && ent->model->brush.num_leafs)
6067 // TODO: use modellight for r_ambient settings on world?
6068 VectorSet(ent->modellight_ambient, 0, 0, 0);
6069 VectorSet(ent->modellight_diffuse, 0, 0, 0);
6070 VectorSet(ent->modellight_lightdir, 0, 0, 1);
6074 // fetch the lighting from the worldmodel data
6075 VectorClear(ent->modellight_ambient);
6076 VectorClear(ent->modellight_diffuse);
6077 VectorClear(tempdiffusenormal);
6078 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6081 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6082 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6083 if(ent->flags & RENDER_EQUALIZE)
6085 // first fix up ambient lighting...
6086 if(r_equalize_entities_minambient.value > 0)
6088 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6091 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6092 if(fa < r_equalize_entities_minambient.value * fd)
6095 // fa'/fd' = minambient
6096 // fa'+0.25*fd' = fa+0.25*fd
6098 // fa' = fd' * minambient
6099 // fd'*(0.25+minambient) = fa+0.25*fd
6101 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6102 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6104 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6105 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
6106 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6107 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6112 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6114 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6115 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6118 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6119 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6120 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6126 VectorSet(ent->modellight_ambient, 1, 1, 1);
6128 // move the light direction into modelspace coordinates for lighting code
6129 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6130 if(VectorLength2(ent->modellight_lightdir) == 0)
6131 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6132 VectorNormalize(ent->modellight_lightdir);
6136 #define MAX_LINEOFSIGHTTRACES 64
6138 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6141 vec3_t boxmins, boxmaxs;
6144 dp_model_t *model = r_refdef.scene.worldmodel;
6146 if (!model || !model->brush.TraceLineOfSight)
6149 // expand the box a little
6150 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6151 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6152 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6153 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6154 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6155 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6158 VectorCopy(eye, start);
6159 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6160 if (model->brush.TraceLineOfSight(model, start, end))
6163 // try various random positions
6164 for (i = 0;i < numsamples;i++)
6166 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6167 if (model->brush.TraceLineOfSight(model, start, end))
6175 static void R_View_UpdateEntityVisible (void)
6180 entity_render_t *ent;
6182 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6183 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6185 // worldmodel can check visibility
6186 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6187 for (i = 0;i < r_refdef.scene.numentities;i++)
6189 ent = r_refdef.scene.entities[i];
6190 if (!(ent->flags & renderimask))
6191 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)))
6192 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))
6193 r_refdef.viewcache.entityvisible[i] = true;
6195 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6197 for (i = 0;i < r_refdef.scene.numentities;i++)
6199 ent = r_refdef.scene.entities[i];
6200 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6202 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6204 continue; // temp entities do pvs only
6205 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6206 ent->last_trace_visibility = realtime;
6207 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6208 r_refdef.viewcache.entityvisible[i] = 0;
6215 // no worldmodel or it can't check visibility
6216 for (i = 0;i < r_refdef.scene.numentities;i++)
6218 ent = r_refdef.scene.entities[i];
6219 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));
6224 /// only used if skyrendermasked, and normally returns false
6225 int R_DrawBrushModelsSky (void)
6228 entity_render_t *ent;
6231 for (i = 0;i < r_refdef.scene.numentities;i++)
6233 if (!r_refdef.viewcache.entityvisible[i])
6235 ent = r_refdef.scene.entities[i];
6236 if (!ent->model || !ent->model->DrawSky)
6238 ent->model->DrawSky(ent);
6244 static void R_DrawNoModel(entity_render_t *ent);
6245 static void R_DrawModels(void)
6248 entity_render_t *ent;
6250 for (i = 0;i < r_refdef.scene.numentities;i++)
6252 if (!r_refdef.viewcache.entityvisible[i])
6254 ent = r_refdef.scene.entities[i];
6255 r_refdef.stats.entities++;
6256 if (ent->model && ent->model->Draw != NULL)
6257 ent->model->Draw(ent);
6263 static void R_DrawModelsDepth(void)
6266 entity_render_t *ent;
6268 for (i = 0;i < r_refdef.scene.numentities;i++)
6270 if (!r_refdef.viewcache.entityvisible[i])
6272 ent = r_refdef.scene.entities[i];
6273 if (ent->model && ent->model->DrawDepth != NULL)
6274 ent->model->DrawDepth(ent);
6278 static void R_DrawModelsDebug(void)
6281 entity_render_t *ent;
6283 for (i = 0;i < r_refdef.scene.numentities;i++)
6285 if (!r_refdef.viewcache.entityvisible[i])
6287 ent = r_refdef.scene.entities[i];
6288 if (ent->model && ent->model->DrawDebug != NULL)
6289 ent->model->DrawDebug(ent);
6293 static void R_DrawModelsAddWaterPlanes(void)
6296 entity_render_t *ent;
6298 for (i = 0;i < r_refdef.scene.numentities;i++)
6300 if (!r_refdef.viewcache.entityvisible[i])
6302 ent = r_refdef.scene.entities[i];
6303 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6304 ent->model->DrawAddWaterPlanes(ent);
6308 static void R_View_SetFrustum(void)
6311 double slopex, slopey;
6312 vec3_t forward, left, up, origin;
6314 // we can't trust r_refdef.view.forward and friends in reflected scenes
6315 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6318 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6319 r_refdef.view.frustum[0].normal[1] = 0 - 0;
6320 r_refdef.view.frustum[0].normal[2] = -1 - 0;
6321 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6322 r_refdef.view.frustum[1].normal[1] = 0 + 0;
6323 r_refdef.view.frustum[1].normal[2] = -1 + 0;
6324 r_refdef.view.frustum[2].normal[0] = 0 - 0;
6325 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6326 r_refdef.view.frustum[2].normal[2] = -1 - 0;
6327 r_refdef.view.frustum[3].normal[0] = 0 + 0;
6328 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6329 r_refdef.view.frustum[3].normal[2] = -1 + 0;
6333 zNear = r_refdef.nearclip;
6334 nudge = 1.0 - 1.0 / (1<<23);
6335 r_refdef.view.frustum[4].normal[0] = 0 - 0;
6336 r_refdef.view.frustum[4].normal[1] = 0 - 0;
6337 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6338 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6339 r_refdef.view.frustum[5].normal[0] = 0 + 0;
6340 r_refdef.view.frustum[5].normal[1] = 0 + 0;
6341 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6342 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6348 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6349 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6350 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6351 r_refdef.view.frustum[0].dist = m[15] - m[12];
6353 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6354 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6355 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6356 r_refdef.view.frustum[1].dist = m[15] + m[12];
6358 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6359 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6360 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6361 r_refdef.view.frustum[2].dist = m[15] - m[13];
6363 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6364 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6365 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6366 r_refdef.view.frustum[3].dist = m[15] + m[13];
6368 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6369 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6370 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6371 r_refdef.view.frustum[4].dist = m[15] - m[14];
6373 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6374 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6375 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6376 r_refdef.view.frustum[5].dist = m[15] + m[14];
6379 if (r_refdef.view.useperspective)
6381 slopex = 1.0 / r_refdef.view.frustum_x;
6382 slopey = 1.0 / r_refdef.view.frustum_y;
6383 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6384 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
6385 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
6386 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
6387 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6389 // Leaving those out was a mistake, those were in the old code, and they
6390 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6391 // I couldn't reproduce it after adding those normalizations. --blub
6392 VectorNormalize(r_refdef.view.frustum[0].normal);
6393 VectorNormalize(r_refdef.view.frustum[1].normal);
6394 VectorNormalize(r_refdef.view.frustum[2].normal);
6395 VectorNormalize(r_refdef.view.frustum[3].normal);
6397 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6398 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]);
6399 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]);
6400 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]);
6401 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]);
6403 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6404 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6405 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6406 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6407 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6411 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6412 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6413 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6414 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6415 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6416 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6417 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6418 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6419 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6420 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6422 r_refdef.view.numfrustumplanes = 5;
6424 if (r_refdef.view.useclipplane)
6426 r_refdef.view.numfrustumplanes = 6;
6427 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6430 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6431 PlaneClassify(r_refdef.view.frustum + i);
6433 // LordHavoc: note to all quake engine coders, Quake had a special case
6434 // for 90 degrees which assumed a square view (wrong), so I removed it,
6435 // Quake2 has it disabled as well.
6437 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6438 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6439 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6440 //PlaneClassify(&frustum[0]);
6442 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6443 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6444 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6445 //PlaneClassify(&frustum[1]);
6447 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6448 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6449 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6450 //PlaneClassify(&frustum[2]);
6452 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6453 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6454 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6455 //PlaneClassify(&frustum[3]);
6458 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6459 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6460 //PlaneClassify(&frustum[4]);
6463 void R_View_Update(void)
6465 R_Main_ResizeViewCache();
6466 R_View_SetFrustum();
6467 R_View_WorldVisibility(r_refdef.view.useclipplane);
6468 R_View_UpdateEntityVisible();
6469 R_View_UpdateEntityLighting();
6472 void R_SetupView(qboolean allowwaterclippingplane)
6474 const float *customclipplane = NULL;
6476 if (r_refdef.view.useclipplane && allowwaterclippingplane)
6478 // LordHavoc: couldn't figure out how to make this approach the
6479 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6480 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6481 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6482 dist = r_refdef.view.clipplane.dist;
6483 plane[0] = r_refdef.view.clipplane.normal[0];
6484 plane[1] = r_refdef.view.clipplane.normal[1];
6485 plane[2] = r_refdef.view.clipplane.normal[2];
6487 customclipplane = plane;
6490 if (!r_refdef.view.useperspective)
6491 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);
6492 else if (vid.stencil && r_useinfinitefarclip.integer)
6493 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);
6495 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);
6496 R_SetViewport(&r_refdef.view.viewport);
6499 void R_EntityMatrix(const matrix4x4_t *matrix)
6501 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6503 gl_modelmatrixchanged = false;
6504 gl_modelmatrix = *matrix;
6505 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6506 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6507 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6508 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6510 switch(vid.renderpath)
6512 case RENDERPATH_GL20:
6513 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6514 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6516 case RENDERPATH_CGGL:
6519 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6520 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6523 case RENDERPATH_GL13:
6524 case RENDERPATH_GL11:
6525 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6531 void R_ResetViewRendering2D(void)
6533 r_viewport_t viewport;
6536 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6537 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);
6538 R_SetViewport(&viewport);
6539 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6540 GL_Color(1, 1, 1, 1);
6541 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6542 GL_BlendFunc(GL_ONE, GL_ZERO);
6543 GL_AlphaTest(false);
6544 GL_ScissorTest(false);
6545 GL_DepthMask(false);
6546 GL_DepthRange(0, 1);
6547 GL_DepthTest(false);
6548 R_EntityMatrix(&identitymatrix);
6549 R_Mesh_ResetTextureState();
6550 GL_PolygonOffset(0, 0);
6551 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6552 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6553 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6554 qglStencilMask(~0);CHECKGLERROR
6555 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6556 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6557 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6560 void R_ResetViewRendering3D(void)
6565 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6566 GL_Color(1, 1, 1, 1);
6567 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6568 GL_BlendFunc(GL_ONE, GL_ZERO);
6569 GL_AlphaTest(false);
6570 GL_ScissorTest(true);
6572 GL_DepthRange(0, 1);
6574 R_EntityMatrix(&identitymatrix);
6575 R_Mesh_ResetTextureState();
6576 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6577 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6578 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6579 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6580 qglStencilMask(~0);CHECKGLERROR
6581 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6582 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6583 GL_CullFace(r_refdef.view.cullface_back);
6586 void R_RenderScene(void);
6587 void R_RenderWaterPlanes(void);
6589 static void R_Water_StartFrame(void)
6592 int waterwidth, waterheight, texturewidth, textureheight;
6593 r_waterstate_waterplane_t *p;
6595 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6598 switch(vid.renderpath)
6600 case RENDERPATH_GL20:
6601 case RENDERPATH_CGGL:
6603 case RENDERPATH_GL13:
6604 case RENDERPATH_GL11:
6608 // set waterwidth and waterheight to the water resolution that will be
6609 // used (often less than the screen resolution for faster rendering)
6610 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6611 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6613 // calculate desired texture sizes
6614 // can't use water if the card does not support the texture size
6615 if (!r_water.integer || r_showsurfaces.integer)
6616 texturewidth = textureheight = waterwidth = waterheight = 0;
6617 else if (vid.support.arb_texture_non_power_of_two)
6619 texturewidth = waterwidth;
6620 textureheight = waterheight;
6624 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
6625 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
6628 // allocate textures as needed
6629 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6631 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6632 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6634 if (p->texture_refraction)
6635 R_FreeTexture(p->texture_refraction);
6636 p->texture_refraction = NULL;
6637 if (p->texture_reflection)
6638 R_FreeTexture(p->texture_reflection);
6639 p->texture_reflection = NULL;
6641 memset(&r_waterstate, 0, sizeof(r_waterstate));
6642 r_waterstate.texturewidth = texturewidth;
6643 r_waterstate.textureheight = textureheight;
6646 if (r_waterstate.texturewidth)
6648 r_waterstate.enabled = true;
6650 // when doing a reduced render (HDR) we want to use a smaller area
6651 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6652 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6654 // set up variables that will be used in shader setup
6655 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6656 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6657 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6658 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6661 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6662 r_waterstate.numwaterplanes = 0;
6665 void R_Water_AddWaterPlane(msurface_t *surface)
6667 int triangleindex, planeindex;
6673 r_waterstate_waterplane_t *p;
6674 texture_t *t = R_GetCurrentTexture(surface->texture);
6675 // just use the first triangle with a valid normal for any decisions
6676 VectorClear(normal);
6677 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6679 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6680 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6681 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6682 TriangleNormal(vert[0], vert[1], vert[2], normal);
6683 if (VectorLength2(normal) >= 0.001)
6687 VectorCopy(normal, plane.normal);
6688 VectorNormalize(plane.normal);
6689 plane.dist = DotProduct(vert[0], plane.normal);
6690 PlaneClassify(&plane);
6691 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6693 // skip backfaces (except if nocullface is set)
6694 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6696 VectorNegate(plane.normal, plane.normal);
6698 PlaneClassify(&plane);
6702 // find a matching plane if there is one
6703 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6704 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6706 if (planeindex >= r_waterstate.maxwaterplanes)
6707 return; // nothing we can do, out of planes
6709 // if this triangle does not fit any known plane rendered this frame, add one
6710 if (planeindex >= r_waterstate.numwaterplanes)
6712 // store the new plane
6713 r_waterstate.numwaterplanes++;
6715 // clear materialflags and pvs
6716 p->materialflags = 0;
6717 p->pvsvalid = false;
6719 // merge this surface's materialflags into the waterplane
6720 p->materialflags |= t->currentmaterialflags;
6721 // merge this surface's PVS into the waterplane
6722 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6723 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6724 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6726 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6731 static void R_Water_ProcessPlanes(void)
6733 r_refdef_view_t originalview;
6734 r_refdef_view_t myview;
6736 r_waterstate_waterplane_t *p;
6738 originalview = r_refdef.view;
6740 // make sure enough textures are allocated
6741 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6743 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6745 if (!p->texture_refraction)
6746 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, NULL);
6747 if (!p->texture_refraction)
6751 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6753 if (!p->texture_reflection)
6754 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, NULL);
6755 if (!p->texture_reflection)
6761 r_refdef.view = originalview;
6762 r_refdef.view.showdebug = false;
6763 r_refdef.view.width = r_waterstate.waterwidth;
6764 r_refdef.view.height = r_waterstate.waterheight;
6765 r_refdef.view.useclipplane = true;
6766 myview = r_refdef.view;
6767 r_waterstate.renderingscene = true;
6768 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6770 // render the normal view scene and copy into texture
6771 // (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)
6772 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6774 r_refdef.view = myview;
6775 r_refdef.view.clipplane = p->plane;
6776 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6777 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6778 PlaneClassify(&r_refdef.view.clipplane);
6780 R_ResetViewRendering3D();
6781 R_ClearScreen(r_refdef.fogenabled);
6785 R_Mesh_CopyToTexture(R_GetTexture(p->texture_refraction), 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6788 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6790 r_refdef.view = myview;
6791 // render reflected scene and copy into texture
6792 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6793 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6794 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6795 r_refdef.view.clipplane = p->plane;
6796 // reverse the cullface settings for this render
6797 r_refdef.view.cullface_front = GL_FRONT;
6798 r_refdef.view.cullface_back = GL_BACK;
6799 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6801 r_refdef.view.usecustompvs = true;
6803 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6805 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6808 R_ResetViewRendering3D();
6809 R_ClearScreen(r_refdef.fogenabled);
6813 R_Mesh_CopyToTexture(R_GetTexture(p->texture_reflection), 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6816 r_waterstate.renderingscene = false;
6817 r_refdef.view = originalview;
6818 R_ResetViewRendering3D();
6819 R_ClearScreen(r_refdef.fogenabled);
6823 r_refdef.view = originalview;
6824 r_waterstate.renderingscene = false;
6825 Cvar_SetValueQuick(&r_water, 0);
6826 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6830 void R_Bloom_StartFrame(void)
6832 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6834 switch(vid.renderpath)
6836 case RENDERPATH_GL20:
6837 case RENDERPATH_CGGL:
6839 case RENDERPATH_GL13:
6840 case RENDERPATH_GL11:
6844 // set bloomwidth and bloomheight to the bloom resolution that will be
6845 // used (often less than the screen resolution for faster rendering)
6846 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6847 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6848 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6849 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6850 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6852 // calculate desired texture sizes
6853 if (vid.support.arb_texture_non_power_of_two)
6855 screentexturewidth = r_refdef.view.width;
6856 screentextureheight = r_refdef.view.height;
6857 bloomtexturewidth = r_bloomstate.bloomwidth;
6858 bloomtextureheight = r_bloomstate.bloomheight;
6862 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6863 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6864 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
6865 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
6868 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))
6870 Cvar_SetValueQuick(&r_hdr, 0);
6871 Cvar_SetValueQuick(&r_bloom, 0);
6872 Cvar_SetValueQuick(&r_motionblur, 0);
6873 Cvar_SetValueQuick(&r_damageblur, 0);
6876 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)))
6877 screentexturewidth = screentextureheight = 0;
6878 if (!r_hdr.integer && !r_bloom.integer)
6879 bloomtexturewidth = bloomtextureheight = 0;
6881 // allocate textures as needed
6882 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
6884 if (r_bloomstate.texture_screen)
6885 R_FreeTexture(r_bloomstate.texture_screen);
6886 r_bloomstate.texture_screen = NULL;
6887 r_bloomstate.screentexturewidth = screentexturewidth;
6888 r_bloomstate.screentextureheight = screentextureheight;
6889 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6890 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
6892 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
6894 if (r_bloomstate.texture_bloom)
6895 R_FreeTexture(r_bloomstate.texture_bloom);
6896 r_bloomstate.texture_bloom = NULL;
6897 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6898 r_bloomstate.bloomtextureheight = bloomtextureheight;
6899 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6900 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6903 // when doing a reduced render (HDR) we want to use a smaller area
6904 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6905 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6906 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6907 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6908 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6910 // set up a texcoord array for the full resolution screen image
6911 // (we have to keep this around to copy back during final render)
6912 r_bloomstate.screentexcoord2f[0] = 0;
6913 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
6914 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
6915 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
6916 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
6917 r_bloomstate.screentexcoord2f[5] = 0;
6918 r_bloomstate.screentexcoord2f[6] = 0;
6919 r_bloomstate.screentexcoord2f[7] = 0;
6921 // set up a texcoord array for the reduced resolution bloom image
6922 // (which will be additive blended over the screen image)
6923 r_bloomstate.bloomtexcoord2f[0] = 0;
6924 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6925 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6926 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6927 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6928 r_bloomstate.bloomtexcoord2f[5] = 0;
6929 r_bloomstate.bloomtexcoord2f[6] = 0;
6930 r_bloomstate.bloomtexcoord2f[7] = 0;
6932 if (r_hdr.integer || r_bloom.integer)
6934 r_bloomstate.enabled = true;
6935 r_bloomstate.hdr = r_hdr.integer != 0;
6938 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);
6941 void R_Bloom_CopyBloomTexture(float colorscale)
6943 r_refdef.stats.bloom++;
6945 // scale down screen texture to the bloom texture size
6947 R_SetViewport(&r_bloomstate.viewport);
6948 GL_BlendFunc(GL_ONE, GL_ZERO);
6949 GL_Color(colorscale, colorscale, colorscale, 1);
6950 // TODO: optimize with multitexture or GLSL
6951 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
6952 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6953 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
6954 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6956 // we now have a bloom image in the framebuffer
6957 // copy it into the bloom image texture for later processing
6958 R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_bloom), 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6959 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6962 void R_Bloom_CopyHDRTexture(void)
6964 R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_bloom), 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6965 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6968 void R_Bloom_MakeTexture(void)
6971 float xoffset, yoffset, r, brighten;
6973 r_refdef.stats.bloom++;
6975 R_ResetViewRendering2D();
6976 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
6977 R_Mesh_ColorPointer(NULL, 0, 0);
6979 // we have a bloom image in the framebuffer
6981 R_SetViewport(&r_bloomstate.viewport);
6983 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6986 r = bound(0, r_bloom_colorexponent.value / x, 1);
6987 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6988 GL_Color(r, r, r, 1);
6989 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6990 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
6991 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
6992 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6994 // copy the vertically blurred bloom view to a texture
6995 GL_ActiveTexture(0);
6997 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
6998 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7001 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7002 brighten = r_bloom_brighten.value;
7004 brighten *= r_hdr_range.value;
7005 brighten = sqrt(brighten);
7007 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7008 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7009 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7011 for (dir = 0;dir < 2;dir++)
7013 // blend on at multiple vertical offsets to achieve a vertical blur
7014 // TODO: do offset blends using GLSL
7015 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7016 GL_BlendFunc(GL_ONE, GL_ZERO);
7017 for (x = -range;x <= range;x++)
7019 if (!dir){xoffset = 0;yoffset = x;}
7020 else {xoffset = x;yoffset = 0;}
7021 xoffset /= (float)r_bloomstate.bloomtexturewidth;
7022 yoffset /= (float)r_bloomstate.bloomtextureheight;
7023 // compute a texcoord array with the specified x and y offset
7024 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7025 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7026 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7027 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7028 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7029 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7030 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7031 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7032 // this r value looks like a 'dot' particle, fading sharply to
7033 // black at the edges
7034 // (probably not realistic but looks good enough)
7035 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7036 //r = brighten/(range*2+1);
7037 r = brighten / (range * 2 + 1);
7039 r *= (1 - x*x/(float)(range*range));
7040 GL_Color(r, r, r, 1);
7041 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7042 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7043 GL_BlendFunc(GL_ONE, GL_ONE);
7046 // copy the vertically blurred bloom view to a texture
7047 GL_ActiveTexture(0);
7049 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7050 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7053 // apply subtract last
7054 // (just like it would be in a GLSL shader)
7055 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7057 GL_BlendFunc(GL_ONE, GL_ZERO);
7058 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7059 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7060 GL_Color(1, 1, 1, 1);
7061 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7062 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7064 GL_BlendFunc(GL_ONE, GL_ONE);
7065 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7066 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7067 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7068 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7069 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7070 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7071 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7073 // copy the darkened bloom view to a texture
7074 R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_bloom), 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7075 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7079 void R_HDR_RenderBloomTexture(void)
7081 int oldwidth, oldheight;
7082 float oldcolorscale;
7084 oldcolorscale = r_refdef.view.colorscale;
7085 oldwidth = r_refdef.view.width;
7086 oldheight = r_refdef.view.height;
7087 r_refdef.view.width = r_bloomstate.bloomwidth;
7088 r_refdef.view.height = r_bloomstate.bloomheight;
7090 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
7091 // TODO: add exposure compensation features
7092 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7094 r_refdef.view.showdebug = false;
7095 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7097 R_ResetViewRendering3D();
7099 R_ClearScreen(r_refdef.fogenabled);
7100 if (r_timereport_active)
7101 R_TimeReport("HDRclear");
7104 if (r_timereport_active)
7105 R_TimeReport("visibility");
7107 // only do secondary renders with HDR if r_hdr is 2 or higher
7108 r_waterstate.numwaterplanes = 0;
7109 if (r_waterstate.enabled && r_hdr.integer >= 2)
7110 R_RenderWaterPlanes();
7112 r_refdef.view.showdebug = true;
7114 r_waterstate.numwaterplanes = 0;
7116 R_ResetViewRendering2D();
7118 R_Bloom_CopyHDRTexture();
7119 R_Bloom_MakeTexture();
7121 // restore the view settings
7122 r_refdef.view.width = oldwidth;
7123 r_refdef.view.height = oldheight;
7124 r_refdef.view.colorscale = oldcolorscale;
7125 r_frame++; // used only by R_GetCurrentTexture
7127 R_ResetViewRendering3D();
7129 R_ClearScreen(r_refdef.fogenabled);
7130 if (r_timereport_active)
7131 R_TimeReport("viewclear");
7134 static void R_BlendView(void)
7136 unsigned int permutation;
7137 float uservecs[4][4];
7139 switch (vid.renderpath)
7141 case RENDERPATH_GL20:
7142 case RENDERPATH_CGGL:
7144 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7145 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7146 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7147 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7148 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7150 if (r_bloomstate.texture_screen)
7152 // make sure the buffer is available
7153 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7155 R_ResetViewRendering2D();
7156 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7157 R_Mesh_ColorPointer(NULL, 0, 0);
7159 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7161 // declare variables
7163 static float avgspeed;
7165 speed = VectorLength(cl.movement_velocity);
7167 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7168 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7170 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7171 speed = bound(0, speed, 1);
7172 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7174 // calculate values into a standard alpha
7175 cl.motionbluralpha = 1 - exp(-
7177 (r_motionblur.value * speed / 80)
7179 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7182 max(0.0001, cl.time - cl.oldtime) // fps independent
7185 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7186 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7188 if (cl.motionbluralpha > 0)
7190 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7191 GL_Color(1, 1, 1, cl.motionbluralpha);
7192 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7193 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7194 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7195 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7199 // copy view into the screen texture
7200 R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_screen), 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7201 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7203 else if (!r_bloomstate.texture_bloom)
7205 // we may still have to do view tint...
7206 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7208 // apply a color tint to the whole view
7209 R_ResetViewRendering2D();
7210 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7211 R_Mesh_ColorPointer(NULL, 0, 0);
7212 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7213 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7214 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7215 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7217 break; // no screen processing, no bloom, skip it
7220 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7222 // render simple bloom effect
7223 // copy the screen and shrink it and darken it for the bloom process
7224 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7225 // make the bloom texture
7226 R_Bloom_MakeTexture();
7229 #if _MSC_VER >= 1400
7230 #define sscanf sscanf_s
7232 memset(uservecs, 0, sizeof(uservecs));
7233 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7234 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7235 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7236 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7238 R_ResetViewRendering2D();
7239 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7240 R_Mesh_ColorPointer(NULL, 0, 0);
7241 GL_Color(1, 1, 1, 1);
7242 GL_BlendFunc(GL_ONE, GL_ZERO);
7243 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7244 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7246 switch(vid.renderpath)
7248 case RENDERPATH_GL20:
7249 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7250 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(r_bloomstate.texture_screen));
7251 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , R_GetTexture(r_bloomstate.texture_bloom ));
7252 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps ));
7253 if (r_glsl_permutation->loc_ViewTintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7254 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime , cl.time);
7255 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7256 if (r_glsl_permutation->loc_UserVec1 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7257 if (r_glsl_permutation->loc_UserVec2 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7258 if (r_glsl_permutation->loc_UserVec3 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7259 if (r_glsl_permutation->loc_UserVec4 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7260 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7262 case RENDERPATH_CGGL:
7264 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7265 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , R_GetTexture(r_bloomstate.texture_screen));CHECKCGERROR
7266 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , R_GetTexture(r_bloomstate.texture_bloom ));CHECKCGERROR
7267 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, R_GetTexture(r_texture_gammaramps ));CHECKCGERROR
7268 if (r_cg_permutation->fp_ViewTintColor ) cgGLSetParameter4f( r_cg_permutation->fp_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);CHECKCGERROR
7269 if (r_cg_permutation->fp_ClientTime ) cgGLSetParameter1f( r_cg_permutation->fp_ClientTime , cl.time);CHECKCGERROR
7270 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7271 if (r_cg_permutation->fp_UserVec1 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);CHECKCGERROR
7272 if (r_cg_permutation->fp_UserVec2 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);CHECKCGERROR
7273 if (r_cg_permutation->fp_UserVec3 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);CHECKCGERROR
7274 if (r_cg_permutation->fp_UserVec4 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);CHECKCGERROR
7275 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
7281 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7282 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7284 case RENDERPATH_GL13:
7285 case RENDERPATH_GL11:
7286 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7288 // apply a color tint to the whole view
7289 R_ResetViewRendering2D();
7290 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7291 R_Mesh_ColorPointer(NULL, 0, 0);
7292 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7293 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7294 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7295 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7301 matrix4x4_t r_waterscrollmatrix;
7303 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7305 if (r_refdef.fog_density)
7307 r_refdef.fogcolor[0] = r_refdef.fog_red;
7308 r_refdef.fogcolor[1] = r_refdef.fog_green;
7309 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7311 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7312 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7313 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7314 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7318 VectorCopy(r_refdef.fogcolor, fogvec);
7319 // color.rgb *= ContrastBoost * SceneBrightness;
7320 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7321 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7322 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7323 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7328 void R_UpdateVariables(void)
7332 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7334 r_refdef.farclip = r_farclip_base.value;
7335 if (r_refdef.scene.worldmodel)
7336 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7337 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7339 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7340 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7341 r_refdef.polygonfactor = 0;
7342 r_refdef.polygonoffset = 0;
7343 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7344 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7346 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7347 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7348 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7349 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7350 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7351 if (r_showsurfaces.integer)
7353 r_refdef.scene.rtworld = false;
7354 r_refdef.scene.rtworldshadows = false;
7355 r_refdef.scene.rtdlight = false;
7356 r_refdef.scene.rtdlightshadows = false;
7357 r_refdef.lightmapintensity = 0;
7360 if (gamemode == GAME_NEHAHRA)
7362 if (gl_fogenable.integer)
7364 r_refdef.oldgl_fogenable = true;
7365 r_refdef.fog_density = gl_fogdensity.value;
7366 r_refdef.fog_red = gl_fogred.value;
7367 r_refdef.fog_green = gl_foggreen.value;
7368 r_refdef.fog_blue = gl_fogblue.value;
7369 r_refdef.fog_alpha = 1;
7370 r_refdef.fog_start = 0;
7371 r_refdef.fog_end = gl_skyclip.value;
7372 r_refdef.fog_height = 1<<30;
7373 r_refdef.fog_fadedepth = 128;
7375 else if (r_refdef.oldgl_fogenable)
7377 r_refdef.oldgl_fogenable = false;
7378 r_refdef.fog_density = 0;
7379 r_refdef.fog_red = 0;
7380 r_refdef.fog_green = 0;
7381 r_refdef.fog_blue = 0;
7382 r_refdef.fog_alpha = 0;
7383 r_refdef.fog_start = 0;
7384 r_refdef.fog_end = 0;
7385 r_refdef.fog_height = 1<<30;
7386 r_refdef.fog_fadedepth = 128;
7390 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7391 r_refdef.fog_start = max(0, r_refdef.fog_start);
7392 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7394 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7396 if (r_refdef.fog_density && r_drawfog.integer)
7398 r_refdef.fogenabled = true;
7399 // this is the point where the fog reaches 0.9986 alpha, which we
7400 // consider a good enough cutoff point for the texture
7401 // (0.9986 * 256 == 255.6)
7402 if (r_fog_exp2.integer)
7403 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7405 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7406 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7407 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7408 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7409 // fog color was already set
7410 // update the fog texture
7411 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)
7412 R_BuildFogTexture();
7415 r_refdef.fogenabled = false;
7417 switch(vid.renderpath)
7419 case RENDERPATH_GL20:
7420 case RENDERPATH_CGGL:
7421 if(v_glslgamma.integer && !vid_gammatables_trivial)
7423 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7425 // build GLSL gamma texture
7426 #define RAMPWIDTH 256
7427 unsigned short ramp[RAMPWIDTH * 3];
7428 unsigned char rampbgr[RAMPWIDTH][4];
7431 r_texture_gammaramps_serial = vid_gammatables_serial;
7433 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7434 for(i = 0; i < RAMPWIDTH; ++i)
7436 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7437 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7438 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7441 if (r_texture_gammaramps)
7443 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7447 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
7453 // remove GLSL gamma texture
7456 case RENDERPATH_GL13:
7457 case RENDERPATH_GL11:
7462 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7463 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7469 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7470 if( scenetype != r_currentscenetype ) {
7471 // store the old scenetype
7472 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7473 r_currentscenetype = scenetype;
7474 // move in the new scene
7475 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7484 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7486 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7487 if( scenetype == r_currentscenetype ) {
7488 return &r_refdef.scene;
7490 return &r_scenes_store[ scenetype ];
7499 void R_RenderView(void)
7501 if (r_timereport_active)
7502 R_TimeReport("start");
7503 r_frame++; // used only by R_GetCurrentTexture
7504 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7506 if (!r_drawentities.integer)
7507 r_refdef.scene.numentities = 0;
7509 R_AnimCache_ClearCache();
7510 R_FrameData_NewFrame();
7512 if (r_refdef.view.isoverlay)
7514 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7515 GL_Clear( GL_DEPTH_BUFFER_BIT );
7516 R_TimeReport("depthclear");
7518 r_refdef.view.showdebug = false;
7520 r_waterstate.enabled = false;
7521 r_waterstate.numwaterplanes = 0;
7529 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7530 return; //Host_Error ("R_RenderView: NULL worldmodel");
7532 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7534 // break apart the view matrix into vectors for various purposes
7535 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7536 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7537 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7538 VectorNegate(r_refdef.view.left, r_refdef.view.right);
7539 // make an inverted copy of the view matrix for tracking sprites
7540 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7542 R_Shadow_UpdateWorldLightSelection();
7544 R_Bloom_StartFrame();
7545 R_Water_StartFrame();
7548 if (r_timereport_active)
7549 R_TimeReport("viewsetup");
7551 R_ResetViewRendering3D();
7553 if (r_refdef.view.clear || r_refdef.fogenabled)
7555 R_ClearScreen(r_refdef.fogenabled);
7556 if (r_timereport_active)
7557 R_TimeReport("viewclear");
7559 r_refdef.view.clear = true;
7561 // this produces a bloom texture to be used in R_BlendView() later
7562 if (r_hdr.integer && r_bloomstate.bloomwidth)
7563 R_HDR_RenderBloomTexture();
7565 r_refdef.view.showdebug = true;
7568 if (r_timereport_active)
7569 R_TimeReport("visibility");
7571 r_waterstate.numwaterplanes = 0;
7572 if (r_waterstate.enabled)
7573 R_RenderWaterPlanes();
7576 r_waterstate.numwaterplanes = 0;
7579 if (r_timereport_active)
7580 R_TimeReport("blendview");
7582 GL_Scissor(0, 0, vid.width, vid.height);
7583 GL_ScissorTest(false);
7587 void R_RenderWaterPlanes(void)
7589 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7591 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7592 if (r_timereport_active)
7593 R_TimeReport("waterworld");
7596 // don't let sound skip if going slow
7597 if (r_refdef.scene.extraupdate)
7600 R_DrawModelsAddWaterPlanes();
7601 if (r_timereport_active)
7602 R_TimeReport("watermodels");
7604 if (r_waterstate.numwaterplanes)
7606 R_Water_ProcessPlanes();
7607 if (r_timereport_active)
7608 R_TimeReport("waterscenes");
7612 extern void R_DrawLightningBeams (void);
7613 extern void VM_CL_AddPolygonsToMeshQueue (void);
7614 extern void R_DrawPortals (void);
7615 extern cvar_t cl_locs_show;
7616 static void R_DrawLocs(void);
7617 static void R_DrawEntityBBoxes(void);
7618 static void R_DrawModelDecals(void);
7619 extern cvar_t cl_decals_newsystem;
7620 extern qboolean r_shadow_usingdeferredprepass;
7621 void R_RenderScene(void)
7623 r_refdef.stats.renders++;
7627 // don't let sound skip if going slow
7628 if (r_refdef.scene.extraupdate)
7631 R_MeshQueue_BeginScene();
7635 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);
7637 if (cl.csqc_vidvars.drawworld)
7639 // don't let sound skip if going slow
7640 if (r_refdef.scene.extraupdate)
7643 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7645 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7646 if (r_timereport_active)
7647 R_TimeReport("worldsky");
7650 if (R_DrawBrushModelsSky() && r_timereport_active)
7651 R_TimeReport("bmodelsky");
7653 if (skyrendermasked && skyrenderlater)
7655 // we have to force off the water clipping plane while rendering sky
7659 if (r_timereport_active)
7660 R_TimeReport("sky");
7664 R_AnimCache_CacheVisibleEntities();
7665 if (r_timereport_active)
7666 R_TimeReport("animation");
7668 R_Shadow_PrepareLights();
7669 if (r_timereport_active)
7670 R_TimeReport("preparelights");
7672 if (r_shadow_usingdeferredprepass)
7673 R_Shadow_DrawPrepass();
7675 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7677 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7678 if (r_timereport_active)
7679 R_TimeReport("worlddepth");
7681 if (r_depthfirst.integer >= 2)
7683 R_DrawModelsDepth();
7684 if (r_timereport_active)
7685 R_TimeReport("modeldepth");
7688 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7690 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7691 if (r_timereport_active)
7692 R_TimeReport("world");
7695 // don't let sound skip if going slow
7696 if (r_refdef.scene.extraupdate)
7700 if (r_timereport_active)
7701 R_TimeReport("models");
7703 // don't let sound skip if going slow
7704 if (r_refdef.scene.extraupdate)
7707 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7709 R_DrawModelShadows();
7710 R_ResetViewRendering3D();
7711 // don't let sound skip if going slow
7712 if (r_refdef.scene.extraupdate)
7716 if (!r_shadow_usingdeferredprepass)
7718 R_Shadow_DrawLights();
7719 if (r_timereport_active)
7720 R_TimeReport("rtlights");
7723 // don't let sound skip if going slow
7724 if (r_refdef.scene.extraupdate)
7727 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7729 R_DrawModelShadows();
7730 R_ResetViewRendering3D();
7731 // don't let sound skip if going slow
7732 if (r_refdef.scene.extraupdate)
7736 if (cl.csqc_vidvars.drawworld)
7738 if (cl_decals_newsystem.integer)
7740 R_DrawModelDecals();
7741 if (r_timereport_active)
7742 R_TimeReport("modeldecals");
7747 if (r_timereport_active)
7748 R_TimeReport("decals");
7752 if (r_timereport_active)
7753 R_TimeReport("particles");
7756 if (r_timereport_active)
7757 R_TimeReport("explosions");
7759 R_DrawLightningBeams();
7760 if (r_timereport_active)
7761 R_TimeReport("lightning");
7764 VM_CL_AddPolygonsToMeshQueue();
7766 if (r_refdef.view.showdebug)
7768 if (cl_locs_show.integer)
7771 if (r_timereport_active)
7772 R_TimeReport("showlocs");
7775 if (r_drawportals.integer)
7778 if (r_timereport_active)
7779 R_TimeReport("portals");
7782 if (r_showbboxes.value > 0)
7784 R_DrawEntityBBoxes();
7785 if (r_timereport_active)
7786 R_TimeReport("bboxes");
7790 R_MeshQueue_RenderTransparent();
7791 if (r_timereport_active)
7792 R_TimeReport("drawtrans");
7794 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))
7796 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7797 if (r_timereport_active)
7798 R_TimeReport("worlddebug");
7799 R_DrawModelsDebug();
7800 if (r_timereport_active)
7801 R_TimeReport("modeldebug");
7804 if (cl.csqc_vidvars.drawworld)
7806 R_Shadow_DrawCoronas();
7807 if (r_timereport_active)
7808 R_TimeReport("coronas");
7811 // don't let sound skip if going slow
7812 if (r_refdef.scene.extraupdate)
7815 R_ResetViewRendering2D();
7818 static const unsigned short bboxelements[36] =
7828 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7831 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7833 RSurf_ActiveWorldEntity();
7835 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7836 GL_DepthMask(false);
7837 GL_DepthRange(0, 1);
7838 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7839 R_Mesh_ResetTextureState();
7841 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7842 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7843 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7844 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7845 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7846 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7847 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7848 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7849 R_FillColors(color4f, 8, cr, cg, cb, ca);
7850 if (r_refdef.fogenabled)
7852 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7854 f1 = RSurf_FogVertex(v);
7856 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7857 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7858 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7861 R_Mesh_VertexPointer(vertex3f, 0, 0);
7862 R_Mesh_ColorPointer(color4f, 0, 0);
7863 R_Mesh_ResetTextureState();
7864 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7865 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
7868 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7872 prvm_edict_t *edict;
7873 prvm_prog_t *prog_save = prog;
7875 // this function draws bounding boxes of server entities
7879 GL_CullFace(GL_NONE);
7880 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7884 for (i = 0;i < numsurfaces;i++)
7886 edict = PRVM_EDICT_NUM(surfacelist[i]);
7887 switch ((int)edict->fields.server->solid)
7889 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7890 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7891 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7892 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7893 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7894 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7896 color[3] *= r_showbboxes.value;
7897 color[3] = bound(0, color[3], 1);
7898 GL_DepthTest(!r_showdisabledepthtest.integer);
7899 GL_CullFace(r_refdef.view.cullface_front);
7900 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7906 static void R_DrawEntityBBoxes(void)
7909 prvm_edict_t *edict;
7911 prvm_prog_t *prog_save = prog;
7913 // this function draws bounding boxes of server entities
7919 for (i = 0;i < prog->num_edicts;i++)
7921 edict = PRVM_EDICT_NUM(i);
7922 if (edict->priv.server->free)
7924 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7925 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7927 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7929 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7930 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7936 static const int nomodelelement3i[24] =
7948 static const unsigned short nomodelelement3s[24] =
7960 static const float nomodelvertex3f[6*3] =
7970 static const float nomodelcolor4f[6*4] =
7972 0.0f, 0.0f, 0.5f, 1.0f,
7973 0.0f, 0.0f, 0.5f, 1.0f,
7974 0.0f, 0.5f, 0.0f, 1.0f,
7975 0.0f, 0.5f, 0.0f, 1.0f,
7976 0.5f, 0.0f, 0.0f, 1.0f,
7977 0.5f, 0.0f, 0.0f, 1.0f
7980 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7986 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);
7988 // this is only called once per entity so numsurfaces is always 1, and
7989 // surfacelist is always {0}, so this code does not handle batches
7991 if (rsurface.ent_flags & RENDER_ADDITIVE)
7993 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7994 GL_DepthMask(false);
7996 else if (rsurface.colormod[3] < 1)
7998 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7999 GL_DepthMask(false);
8003 GL_BlendFunc(GL_ONE, GL_ZERO);
8006 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8007 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8008 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8009 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8010 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8011 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8012 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8013 R_Mesh_ColorPointer(color4f, 0, 0);
8014 for (i = 0, c = color4f;i < 6;i++, c += 4)
8016 c[0] *= rsurface.colormod[0];
8017 c[1] *= rsurface.colormod[1];
8018 c[2] *= rsurface.colormod[2];
8019 c[3] *= rsurface.colormod[3];
8021 if (r_refdef.fogenabled)
8023 for (i = 0, c = color4f;i < 6;i++, c += 4)
8025 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8027 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8028 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8029 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8032 R_Mesh_ResetTextureState();
8033 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8036 void R_DrawNoModel(entity_render_t *ent)
8039 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8040 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8041 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8043 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8046 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8048 vec3_t right1, right2, diff, normal;
8050 VectorSubtract (org2, org1, normal);
8052 // calculate 'right' vector for start
8053 VectorSubtract (r_refdef.view.origin, org1, diff);
8054 CrossProduct (normal, diff, right1);
8055 VectorNormalize (right1);
8057 // calculate 'right' vector for end
8058 VectorSubtract (r_refdef.view.origin, org2, diff);
8059 CrossProduct (normal, diff, right2);
8060 VectorNormalize (right2);
8062 vert[ 0] = org1[0] + width * right1[0];
8063 vert[ 1] = org1[1] + width * right1[1];
8064 vert[ 2] = org1[2] + width * right1[2];
8065 vert[ 3] = org1[0] - width * right1[0];
8066 vert[ 4] = org1[1] - width * right1[1];
8067 vert[ 5] = org1[2] - width * right1[2];
8068 vert[ 6] = org2[0] - width * right2[0];
8069 vert[ 7] = org2[1] - width * right2[1];
8070 vert[ 8] = org2[2] - width * right2[2];
8071 vert[ 9] = org2[0] + width * right2[0];
8072 vert[10] = org2[1] + width * right2[1];
8073 vert[11] = org2[2] + width * right2[2];
8076 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)
8078 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8079 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8080 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8081 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8082 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8083 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8084 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8085 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8086 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8087 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8088 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8089 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8092 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8097 VectorSet(v, x, y, z);
8098 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8099 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8101 if (i == mesh->numvertices)
8103 if (mesh->numvertices < mesh->maxvertices)
8105 VectorCopy(v, vertex3f);
8106 mesh->numvertices++;
8108 return mesh->numvertices;
8114 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8118 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8119 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8120 e = mesh->element3i + mesh->numtriangles * 3;
8121 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8123 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8124 if (mesh->numtriangles < mesh->maxtriangles)
8129 mesh->numtriangles++;
8131 element[1] = element[2];
8135 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8139 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8140 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8141 e = mesh->element3i + mesh->numtriangles * 3;
8142 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8144 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8145 if (mesh->numtriangles < mesh->maxtriangles)
8150 mesh->numtriangles++;
8152 element[1] = element[2];
8156 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8157 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8159 int planenum, planenum2;
8162 mplane_t *plane, *plane2;
8164 double temppoints[2][256*3];
8165 // figure out how large a bounding box we need to properly compute this brush
8167 for (w = 0;w < numplanes;w++)
8168 maxdist = max(maxdist, fabs(planes[w].dist));
8169 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8170 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8171 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8175 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8176 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8178 if (planenum2 == planenum)
8180 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);
8183 if (tempnumpoints < 3)
8185 // generate elements forming a triangle fan for this polygon
8186 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8190 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)
8192 texturelayer_t *layer;
8193 layer = t->currentlayers + t->currentnumlayers++;
8195 layer->depthmask = depthmask;
8196 layer->blendfunc1 = blendfunc1;
8197 layer->blendfunc2 = blendfunc2;
8198 layer->texture = texture;
8199 layer->texmatrix = *matrix;
8200 layer->color[0] = r;
8201 layer->color[1] = g;
8202 layer->color[2] = b;
8203 layer->color[3] = a;
8206 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8209 index = parms[2] + r_refdef.scene.time * parms[3];
8210 index -= floor(index);
8214 case Q3WAVEFUNC_NONE:
8215 case Q3WAVEFUNC_NOISE:
8216 case Q3WAVEFUNC_COUNT:
8219 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8220 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8221 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8222 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8223 case Q3WAVEFUNC_TRIANGLE:
8225 f = index - floor(index);
8236 return (float)(parms[0] + parms[1] * f);
8239 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8244 matrix4x4_t matrix, temp;
8245 switch(tcmod->tcmod)
8249 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8250 matrix = r_waterscrollmatrix;
8252 matrix = identitymatrix;
8254 case Q3TCMOD_ENTITYTRANSLATE:
8255 // this is used in Q3 to allow the gamecode to control texcoord
8256 // scrolling on the entity, which is not supported in darkplaces yet.
8257 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8259 case Q3TCMOD_ROTATE:
8260 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8261 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8262 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8265 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8267 case Q3TCMOD_SCROLL:
8268 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8270 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8271 w = (int) tcmod->parms[0];
8272 h = (int) tcmod->parms[1];
8273 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8275 idx = (int) floor(f * w * h);
8276 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8278 case Q3TCMOD_STRETCH:
8279 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8280 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8282 case Q3TCMOD_TRANSFORM:
8283 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8284 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8285 VectorSet(tcmat + 6, 0 , 0 , 1);
8286 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8287 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8289 case Q3TCMOD_TURBULENT:
8290 // this is handled in the RSurf_PrepareVertices function
8291 matrix = identitymatrix;
8295 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8298 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8300 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8301 char name[MAX_QPATH];
8302 skinframe_t *skinframe;
8303 unsigned char pixels[296*194];
8304 strlcpy(cache->name, skinname, sizeof(cache->name));
8305 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8306 if (developer_loading.integer)
8307 Con_Printf("loading %s\n", name);
8308 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8309 if (!skinframe || !skinframe->base)
8312 fs_offset_t filesize;
8314 f = FS_LoadFile(name, tempmempool, true, &filesize);
8317 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8318 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8322 cache->skinframe = skinframe;
8325 texture_t *R_GetCurrentTexture(texture_t *t)
8328 const entity_render_t *ent = rsurface.entity;
8329 dp_model_t *model = ent->model;
8330 q3shaderinfo_layer_tcmod_t *tcmod;
8332 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
8333 return t->currentframe;
8334 t->update_lastrenderframe = r_frame;
8335 t->update_lastrenderentity = (void *)ent;
8337 // switch to an alternate material if this is a q1bsp animated material
8339 texture_t *texture = t;
8340 int s = rsurface.ent_skinnum;
8341 if ((unsigned int)s >= (unsigned int)model->numskins)
8343 if (model->skinscenes)
8345 if (model->skinscenes[s].framecount > 1)
8346 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8348 s = model->skinscenes[s].firstframe;
8351 t = t + s * model->num_surfaces;
8354 // use an alternate animation if the entity's frame is not 0,
8355 // and only if the texture has an alternate animation
8356 if (rsurface.ent_alttextures && t->anim_total[1])
8357 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8359 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8361 texture->currentframe = t;
8364 // update currentskinframe to be a qw skin or animation frame
8365 if (rsurface.ent_qwskin >= 0)
8367 i = rsurface.ent_qwskin;
8368 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8370 r_qwskincache_size = cl.maxclients;
8372 Mem_Free(r_qwskincache);
8373 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8375 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8376 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8377 t->currentskinframe = r_qwskincache[i].skinframe;
8378 if (t->currentskinframe == NULL)
8379 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8381 else if (t->numskinframes >= 2)
8382 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8383 if (t->backgroundnumskinframes >= 2)
8384 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8386 t->currentmaterialflags = t->basematerialflags;
8387 t->currentalpha = rsurface.colormod[3];
8388 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8389 t->currentalpha *= r_wateralpha.value;
8390 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8391 t->currentalpha *= t->r_water_wateralpha;
8392 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8393 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8394 if (!(rsurface.ent_flags & RENDER_LIGHT))
8395 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8396 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8398 // pick a model lighting mode
8399 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8400 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8402 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8404 if (rsurface.ent_flags & RENDER_ADDITIVE)
8405 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8406 else if (t->currentalpha < 1)
8407 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8408 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8409 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8410 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8411 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8412 if (t->backgroundnumskinframes)
8413 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8414 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8416 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8417 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8420 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8421 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8422 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8424 // there is no tcmod
8425 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8427 t->currenttexmatrix = r_waterscrollmatrix;
8428 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8430 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8432 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8433 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8436 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8437 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8438 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8439 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8441 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8442 if (t->currentskinframe->qpixels)
8443 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8444 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8445 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8446 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8447 t->nmaptexture = t->currentskinframe->nmap;
8448 t->glosstexture = r_texture_black;
8449 t->glowtexture = t->currentskinframe->glow;
8450 t->fogtexture = t->currentskinframe->fog;
8451 if (t->backgroundnumskinframes)
8453 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8454 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8455 t->backgroundglosstexture = r_texture_black;
8456 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8460 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8461 t->backgroundnmaptexture = r_texture_blanknormalmap;
8462 t->backgroundglosstexture = r_texture_black;
8463 t->backgroundglowtexture = NULL;
8465 t->specularpower = r_shadow_glossexponent.value;
8466 // TODO: store reference values for these in the texture?
8467 t->specularscale = 0;
8468 if (r_shadow_gloss.integer > 0)
8470 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8472 if (r_shadow_glossintensity.value > 0)
8474 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8475 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8476 t->specularscale = r_shadow_glossintensity.value;
8479 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8481 t->glosstexture = r_texture_white;
8482 t->backgroundglosstexture = r_texture_white;
8483 t->specularscale = r_shadow_gloss2intensity.value;
8484 t->specularpower = r_shadow_gloss2exponent.value;
8487 t->specularscale *= t->specularscalemod;
8488 t->specularpower *= t->specularpowermod;
8490 // lightmaps mode looks bad with dlights using actual texturing, so turn
8491 // off the colormap and glossmap, but leave the normalmap on as it still
8492 // accurately represents the shading involved
8493 if (gl_lightmaps.integer)
8495 t->basetexture = r_texture_grey128;
8496 t->pantstexture = r_texture_black;
8497 t->shirttexture = r_texture_black;
8498 t->nmaptexture = r_texture_blanknormalmap;
8499 t->glosstexture = r_texture_black;
8500 t->glowtexture = NULL;
8501 t->fogtexture = NULL;
8502 t->backgroundbasetexture = NULL;
8503 t->backgroundnmaptexture = r_texture_blanknormalmap;
8504 t->backgroundglosstexture = r_texture_black;
8505 t->backgroundglowtexture = NULL;
8506 t->specularscale = 0;
8507 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8510 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8511 VectorClear(t->dlightcolor);
8512 t->currentnumlayers = 0;
8513 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8515 int blendfunc1, blendfunc2;
8517 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8519 blendfunc1 = GL_SRC_ALPHA;
8520 blendfunc2 = GL_ONE;
8522 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8524 blendfunc1 = GL_SRC_ALPHA;
8525 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8527 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8529 blendfunc1 = t->customblendfunc[0];
8530 blendfunc2 = t->customblendfunc[1];
8534 blendfunc1 = GL_ONE;
8535 blendfunc2 = GL_ZERO;
8537 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8538 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8540 // fullbright is not affected by r_refdef.lightmapintensity
8541 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]);
8542 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8543 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &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]);
8544 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8545 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &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]);
8549 vec3_t ambientcolor;
8551 // set the color tint used for lights affecting this surface
8552 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8554 // q3bsp has no lightmap updates, so the lightstylevalue that
8555 // would normally be baked into the lightmap must be
8556 // applied to the color
8557 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8558 if (model->type == mod_brushq3)
8559 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8560 colorscale *= r_refdef.lightmapintensity;
8561 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8562 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8563 // basic lit geometry
8564 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]);
8565 // add pants/shirt if needed
8566 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8567 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &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]);
8568 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8569 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &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]);
8570 // now add ambient passes if needed
8571 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8573 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]);
8574 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8575 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8576 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8577 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8580 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8581 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
8582 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8584 // if this is opaque use alpha blend which will darken the earlier
8587 // if this is an alpha blended material, all the earlier passes
8588 // were darkened by fog already, so we only need to add the fog
8589 // color ontop through the fog mask texture
8591 // if this is an additive blended material, all the earlier passes
8592 // were darkened by fog already, and we should not add fog color
8593 // (because the background was not darkened, there is no fog color
8594 // that was lost behind it).
8595 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
8599 return t->currentframe;
8602 rsurfacestate_t rsurface;
8604 void R_Mesh_ResizeArrays(int newvertices)
8607 if (rsurface.array_size >= newvertices)
8609 if (rsurface.array_modelvertex3f)
8610 Mem_Free(rsurface.array_modelvertex3f);
8611 rsurface.array_size = (newvertices + 1023) & ~1023;
8612 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8613 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
8614 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
8615 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
8616 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
8617 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
8618 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8619 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8620 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
8621 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
8622 rsurface.array_color4f = base + rsurface.array_size * 27;
8623 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8626 void RSurf_ActiveWorldEntity(void)
8628 dp_model_t *model = r_refdef.scene.worldmodel;
8629 //if (rsurface.entity == r_refdef.scene.worldentity)
8631 rsurface.entity = r_refdef.scene.worldentity;
8632 rsurface.skeleton = NULL;
8633 rsurface.ent_skinnum = 0;
8634 rsurface.ent_qwskin = -1;
8635 rsurface.ent_shadertime = 0;
8636 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8637 if (rsurface.array_size < model->surfmesh.num_vertices)
8638 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8639 rsurface.matrix = identitymatrix;
8640 rsurface.inversematrix = identitymatrix;
8641 rsurface.matrixscale = 1;
8642 rsurface.inversematrixscale = 1;
8643 R_EntityMatrix(&identitymatrix);
8644 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8645 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8646 rsurface.fograngerecip = r_refdef.fograngerecip;
8647 rsurface.fogheightfade = r_refdef.fogheightfade;
8648 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8649 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8650 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8651 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8652 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8653 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8654 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8655 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8656 rsurface.colormod[3] = 1;
8657 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);
8658 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8659 rsurface.frameblend[0].lerp = 1;
8660 rsurface.ent_alttextures = false;
8661 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8662 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8663 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8664 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8665 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8666 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8667 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8668 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8669 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8670 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8671 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8672 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8673 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8674 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8675 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8676 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8677 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8678 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8679 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8680 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8681 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8682 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8683 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8684 rsurface.modelelement3i = model->surfmesh.data_element3i;
8685 rsurface.modelelement3s = model->surfmesh.data_element3s;
8686 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8687 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8688 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8689 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8690 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8691 rsurface.modelsurfaces = model->data_surfaces;
8692 rsurface.generatedvertex = false;
8693 rsurface.vertex3f = rsurface.modelvertex3f;
8694 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8695 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8696 rsurface.svector3f = rsurface.modelsvector3f;
8697 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8698 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8699 rsurface.tvector3f = rsurface.modeltvector3f;
8700 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8701 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8702 rsurface.normal3f = rsurface.modelnormal3f;
8703 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8704 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8705 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8708 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8710 dp_model_t *model = ent->model;
8711 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8713 rsurface.entity = (entity_render_t *)ent;
8714 rsurface.skeleton = ent->skeleton;
8715 rsurface.ent_skinnum = ent->skinnum;
8716 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;
8717 rsurface.ent_shadertime = ent->shadertime;
8718 rsurface.ent_flags = ent->flags;
8719 if (rsurface.array_size < model->surfmesh.num_vertices)
8720 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8721 rsurface.matrix = ent->matrix;
8722 rsurface.inversematrix = ent->inversematrix;
8723 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8724 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8725 R_EntityMatrix(&rsurface.matrix);
8726 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8727 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8728 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8729 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8730 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8731 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8732 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8733 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8734 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8735 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8736 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8737 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8738 rsurface.colormod[3] = ent->alpha;
8739 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8740 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8741 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8742 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8743 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8744 if (ent->model->brush.submodel && !prepass)
8746 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8747 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8749 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8751 if (ent->animcache_vertex3f && !r_framedata_failed)
8753 rsurface.modelvertex3f = ent->animcache_vertex3f;
8754 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8755 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8756 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8758 else if (wanttangents)
8760 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8761 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
8762 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
8763 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8764 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
8766 else if (wantnormals)
8768 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8769 rsurface.modelsvector3f = NULL;
8770 rsurface.modeltvector3f = NULL;
8771 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8772 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
8776 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8777 rsurface.modelsvector3f = NULL;
8778 rsurface.modeltvector3f = NULL;
8779 rsurface.modelnormal3f = NULL;
8780 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
8782 rsurface.modelvertex3f_bufferobject = 0;
8783 rsurface.modelvertex3f_bufferoffset = 0;
8784 rsurface.modelsvector3f_bufferobject = 0;
8785 rsurface.modelsvector3f_bufferoffset = 0;
8786 rsurface.modeltvector3f_bufferobject = 0;
8787 rsurface.modeltvector3f_bufferoffset = 0;
8788 rsurface.modelnormal3f_bufferobject = 0;
8789 rsurface.modelnormal3f_bufferoffset = 0;
8790 rsurface.generatedvertex = true;
8794 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8795 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8796 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8797 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8798 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8799 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8800 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8801 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8802 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8803 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8804 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8805 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8806 rsurface.generatedvertex = false;
8808 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8809 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8810 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8811 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8812 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8813 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8814 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8815 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8816 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8817 rsurface.modelelement3i = model->surfmesh.data_element3i;
8818 rsurface.modelelement3s = model->surfmesh.data_element3s;
8819 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8820 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8821 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8822 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8823 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8824 rsurface.modelsurfaces = model->data_surfaces;
8825 rsurface.vertex3f = rsurface.modelvertex3f;
8826 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8827 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8828 rsurface.svector3f = rsurface.modelsvector3f;
8829 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8830 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8831 rsurface.tvector3f = rsurface.modeltvector3f;
8832 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8833 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8834 rsurface.normal3f = rsurface.modelnormal3f;
8835 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8836 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8837 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8840 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)
8842 rsurface.entity = r_refdef.scene.worldentity;
8843 rsurface.skeleton = NULL;
8844 rsurface.ent_skinnum = 0;
8845 rsurface.ent_qwskin = -1;
8846 rsurface.ent_shadertime = shadertime;
8847 rsurface.ent_flags = entflags;
8848 rsurface.modelnum_vertices = numvertices;
8849 rsurface.modelnum_triangles = numtriangles;
8850 if (rsurface.array_size < rsurface.modelnum_vertices)
8851 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
8852 rsurface.matrix = *matrix;
8853 rsurface.inversematrix = *inversematrix;
8854 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8855 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8856 R_EntityMatrix(&rsurface.matrix);
8857 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8858 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8859 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8860 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8861 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8862 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8863 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8864 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8865 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8866 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8867 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8868 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8869 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);
8870 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8871 rsurface.frameblend[0].lerp = 1;
8872 rsurface.ent_alttextures = false;
8873 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8874 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8877 rsurface.modelvertex3f = vertex3f;
8878 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
8879 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
8880 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8882 else if (wantnormals)
8884 rsurface.modelvertex3f = vertex3f;
8885 rsurface.modelsvector3f = NULL;
8886 rsurface.modeltvector3f = NULL;
8887 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8891 rsurface.modelvertex3f = vertex3f;
8892 rsurface.modelsvector3f = NULL;
8893 rsurface.modeltvector3f = NULL;
8894 rsurface.modelnormal3f = NULL;
8896 rsurface.modelvertex3f_bufferobject = 0;
8897 rsurface.modelvertex3f_bufferoffset = 0;
8898 rsurface.modelsvector3f_bufferobject = 0;
8899 rsurface.modelsvector3f_bufferoffset = 0;
8900 rsurface.modeltvector3f_bufferobject = 0;
8901 rsurface.modeltvector3f_bufferoffset = 0;
8902 rsurface.modelnormal3f_bufferobject = 0;
8903 rsurface.modelnormal3f_bufferoffset = 0;
8904 rsurface.generatedvertex = true;
8905 rsurface.modellightmapcolor4f = color4f;
8906 rsurface.modellightmapcolor4f_bufferobject = 0;
8907 rsurface.modellightmapcolor4f_bufferoffset = 0;
8908 rsurface.modeltexcoordtexture2f = texcoord2f;
8909 rsurface.modeltexcoordtexture2f_bufferobject = 0;
8910 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8911 rsurface.modeltexcoordlightmap2f = NULL;
8912 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
8913 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8914 rsurface.modelelement3i = element3i;
8915 rsurface.modelelement3s = element3s;
8916 rsurface.modelelement3i_bufferobject = 0;
8917 rsurface.modelelement3s_bufferobject = 0;
8918 rsurface.modellightmapoffsets = NULL;
8919 rsurface.modelsurfaces = NULL;
8920 rsurface.vertex3f = rsurface.modelvertex3f;
8921 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8922 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8923 rsurface.svector3f = rsurface.modelsvector3f;
8924 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8925 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8926 rsurface.tvector3f = rsurface.modeltvector3f;
8927 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8928 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8929 rsurface.normal3f = rsurface.modelnormal3f;
8930 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8931 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8932 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8934 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
8936 if ((wantnormals || wanttangents) && !normal3f)
8937 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8938 if (wanttangents && !svector3f)
8939 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);
8943 float RSurf_FogPoint(const float *v)
8945 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8946 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8947 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8948 float FogHeightFade = r_refdef.fogheightfade;
8950 unsigned int fogmasktableindex;
8951 if (r_refdef.fogplaneviewabove)
8952 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8954 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8955 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8956 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8959 float RSurf_FogVertex(const float *v)
8961 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8962 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8963 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8964 float FogHeightFade = rsurface.fogheightfade;
8966 unsigned int fogmasktableindex;
8967 if (r_refdef.fogplaneviewabove)
8968 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8970 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8971 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8972 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8975 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8976 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8979 int texturesurfaceindex;
8984 const float *v1, *in_tc;
8986 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8988 q3shaderinfo_deform_t *deform;
8989 // 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
8990 if (rsurface.generatedvertex)
8992 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
8993 generatenormals = true;
8994 for (i = 0;i < Q3MAXDEFORMS;i++)
8996 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
8998 generatetangents = true;
8999 generatenormals = true;
9001 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9002 generatenormals = true;
9004 if (generatenormals && !rsurface.modelnormal3f)
9006 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9007 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9008 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9009 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9011 if (generatetangents && !rsurface.modelsvector3f)
9013 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9014 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9015 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9016 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9017 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9018 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9019 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);
9022 rsurface.vertex3f = rsurface.modelvertex3f;
9023 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9024 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9025 rsurface.svector3f = rsurface.modelsvector3f;
9026 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9027 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9028 rsurface.tvector3f = rsurface.modeltvector3f;
9029 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9030 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9031 rsurface.normal3f = rsurface.modelnormal3f;
9032 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9033 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9034 // if vertices are deformed (sprite flares and things in maps, possibly
9035 // water waves, bulges and other deformations), generate them into
9036 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9037 // (may be static model data or generated data for an animated model, or
9038 // the previous deform pass)
9039 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9041 switch (deform->deform)
9044 case Q3DEFORM_PROJECTIONSHADOW:
9045 case Q3DEFORM_TEXT0:
9046 case Q3DEFORM_TEXT1:
9047 case Q3DEFORM_TEXT2:
9048 case Q3DEFORM_TEXT3:
9049 case Q3DEFORM_TEXT4:
9050 case Q3DEFORM_TEXT5:
9051 case Q3DEFORM_TEXT6:
9052 case Q3DEFORM_TEXT7:
9055 case Q3DEFORM_AUTOSPRITE:
9056 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9057 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9058 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9059 VectorNormalize(newforward);
9060 VectorNormalize(newright);
9061 VectorNormalize(newup);
9062 // make deformed versions of only the model vertices used by the specified surfaces
9063 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9065 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9066 // a single autosprite surface can contain multiple sprites...
9067 for (j = 0;j < surface->num_vertices - 3;j += 4)
9069 VectorClear(center);
9070 for (i = 0;i < 4;i++)
9071 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9072 VectorScale(center, 0.25f, center);
9073 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9074 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9075 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9076 for (i = 0;i < 4;i++)
9078 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9079 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9082 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);
9083 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);
9085 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9086 rsurface.vertex3f_bufferobject = 0;
9087 rsurface.vertex3f_bufferoffset = 0;
9088 rsurface.svector3f = rsurface.array_deformedsvector3f;
9089 rsurface.svector3f_bufferobject = 0;
9090 rsurface.svector3f_bufferoffset = 0;
9091 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9092 rsurface.tvector3f_bufferobject = 0;
9093 rsurface.tvector3f_bufferoffset = 0;
9094 rsurface.normal3f = rsurface.array_deformednormal3f;
9095 rsurface.normal3f_bufferobject = 0;
9096 rsurface.normal3f_bufferoffset = 0;
9098 case Q3DEFORM_AUTOSPRITE2:
9099 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9100 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9101 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9102 VectorNormalize(newforward);
9103 VectorNormalize(newright);
9104 VectorNormalize(newup);
9105 // make deformed versions of only the model vertices used by the specified surfaces
9106 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9108 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9109 const float *v1, *v2;
9119 memset(shortest, 0, sizeof(shortest));
9120 // a single autosprite surface can contain multiple sprites...
9121 for (j = 0;j < surface->num_vertices - 3;j += 4)
9123 VectorClear(center);
9124 for (i = 0;i < 4;i++)
9125 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9126 VectorScale(center, 0.25f, center);
9127 // find the two shortest edges, then use them to define the
9128 // axis vectors for rotating around the central axis
9129 for (i = 0;i < 6;i++)
9131 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9132 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9134 Debug_PolygonBegin(NULL, 0);
9135 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9136 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);
9137 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9140 l = VectorDistance2(v1, v2);
9141 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9143 l += (1.0f / 1024.0f);
9144 if (shortest[0].length2 > l || i == 0)
9146 shortest[1] = shortest[0];
9147 shortest[0].length2 = l;
9148 shortest[0].v1 = v1;
9149 shortest[0].v2 = v2;
9151 else if (shortest[1].length2 > l || i == 1)
9153 shortest[1].length2 = l;
9154 shortest[1].v1 = v1;
9155 shortest[1].v2 = v2;
9158 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9159 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9161 Debug_PolygonBegin(NULL, 0);
9162 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9163 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);
9164 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9167 // this calculates the right vector from the shortest edge
9168 // and the up vector from the edge midpoints
9169 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9170 VectorNormalize(right);
9171 VectorSubtract(end, start, up);
9172 VectorNormalize(up);
9173 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9174 VectorSubtract(rsurface.localvieworigin, center, forward);
9175 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9176 VectorNegate(forward, forward);
9177 VectorReflect(forward, 0, up, forward);
9178 VectorNormalize(forward);
9179 CrossProduct(up, forward, newright);
9180 VectorNormalize(newright);
9182 Debug_PolygonBegin(NULL, 0);
9183 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);
9184 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9185 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9189 Debug_PolygonBegin(NULL, 0);
9190 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9191 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9192 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9195 // rotate the quad around the up axis vector, this is made
9196 // especially easy by the fact we know the quad is flat,
9197 // so we only have to subtract the center position and
9198 // measure distance along the right vector, and then
9199 // multiply that by the newright vector and add back the
9201 // we also need to subtract the old position to undo the
9202 // displacement from the center, which we do with a
9203 // DotProduct, the subtraction/addition of center is also
9204 // optimized into DotProducts here
9205 l = DotProduct(right, center);
9206 for (i = 0;i < 4;i++)
9208 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9209 f = DotProduct(right, v1) - l;
9210 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9213 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);
9214 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);
9216 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9217 rsurface.vertex3f_bufferobject = 0;
9218 rsurface.vertex3f_bufferoffset = 0;
9219 rsurface.svector3f = rsurface.array_deformedsvector3f;
9220 rsurface.svector3f_bufferobject = 0;
9221 rsurface.svector3f_bufferoffset = 0;
9222 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9223 rsurface.tvector3f_bufferobject = 0;
9224 rsurface.tvector3f_bufferoffset = 0;
9225 rsurface.normal3f = rsurface.array_deformednormal3f;
9226 rsurface.normal3f_bufferobject = 0;
9227 rsurface.normal3f_bufferoffset = 0;
9229 case Q3DEFORM_NORMAL:
9230 // deform the normals to make reflections wavey
9231 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9233 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9234 for (j = 0;j < surface->num_vertices;j++)
9237 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9238 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9239 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9240 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9241 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9242 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9243 VectorNormalize(normal);
9245 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);
9247 rsurface.svector3f = rsurface.array_deformedsvector3f;
9248 rsurface.svector3f_bufferobject = 0;
9249 rsurface.svector3f_bufferoffset = 0;
9250 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9251 rsurface.tvector3f_bufferobject = 0;
9252 rsurface.tvector3f_bufferoffset = 0;
9253 rsurface.normal3f = rsurface.array_deformednormal3f;
9254 rsurface.normal3f_bufferobject = 0;
9255 rsurface.normal3f_bufferoffset = 0;
9258 // deform vertex array to make wavey water and flags and such
9259 waveparms[0] = deform->waveparms[0];
9260 waveparms[1] = deform->waveparms[1];
9261 waveparms[2] = deform->waveparms[2];
9262 waveparms[3] = deform->waveparms[3];
9263 // this is how a divisor of vertex influence on deformation
9264 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9265 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9266 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9268 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9269 for (j = 0;j < surface->num_vertices;j++)
9271 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
9272 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
9273 // if the wavefunc depends on time, evaluate it per-vertex
9276 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9277 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9279 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
9282 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9283 rsurface.vertex3f_bufferobject = 0;
9284 rsurface.vertex3f_bufferoffset = 0;
9286 case Q3DEFORM_BULGE:
9287 // deform vertex array to make the surface have moving bulges
9288 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9290 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9291 for (j = 0;j < surface->num_vertices;j++)
9293 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9294 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9297 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9298 rsurface.vertex3f_bufferobject = 0;
9299 rsurface.vertex3f_bufferoffset = 0;
9302 // deform vertex array
9303 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9304 VectorScale(deform->parms, scale, waveparms);
9305 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9307 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9308 for (j = 0;j < surface->num_vertices;j++)
9309 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9311 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9312 rsurface.vertex3f_bufferobject = 0;
9313 rsurface.vertex3f_bufferoffset = 0;
9317 // generate texcoords based on the chosen texcoord source
9318 switch(rsurface.texture->tcgen.tcgen)
9321 case Q3TCGEN_TEXTURE:
9322 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9323 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
9324 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9326 case Q3TCGEN_LIGHTMAP:
9327 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
9328 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9329 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9331 case Q3TCGEN_VECTOR:
9332 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9334 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9335 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)
9337 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9338 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9341 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9342 rsurface.texcoordtexture2f_bufferobject = 0;
9343 rsurface.texcoordtexture2f_bufferoffset = 0;
9345 case Q3TCGEN_ENVIRONMENT:
9346 // make environment reflections using a spheremap
9347 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9349 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9350 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9351 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9352 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9353 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9355 // identical to Q3A's method, but executed in worldspace so
9356 // carried models can be shiny too
9358 float viewer[3], d, reflected[3], worldreflected[3];
9360 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9361 // VectorNormalize(viewer);
9363 d = DotProduct(normal, viewer);
9365 reflected[0] = normal[0]*2*d - viewer[0];
9366 reflected[1] = normal[1]*2*d - viewer[1];
9367 reflected[2] = normal[2]*2*d - viewer[2];
9368 // note: this is proportinal to viewer, so we can normalize later
9370 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9371 VectorNormalize(worldreflected);
9373 // note: this sphere map only uses world x and z!
9374 // so positive and negative y will LOOK THE SAME.
9375 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9376 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9379 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9380 rsurface.texcoordtexture2f_bufferobject = 0;
9381 rsurface.texcoordtexture2f_bufferoffset = 0;
9384 // the only tcmod that needs software vertex processing is turbulent, so
9385 // check for it here and apply the changes if needed
9386 // and we only support that as the first one
9387 // (handling a mixture of turbulent and other tcmods would be problematic
9388 // without punting it entirely to a software path)
9389 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9391 amplitude = rsurface.texture->tcmods[0].parms[1];
9392 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9393 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9395 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9396 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)
9398 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9399 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9402 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9403 rsurface.texcoordtexture2f_bufferobject = 0;
9404 rsurface.texcoordtexture2f_bufferoffset = 0;
9406 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9407 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9408 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9409 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9412 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9415 const msurface_t *surface = texturesurfacelist[0];
9416 const msurface_t *surface2;
9421 // TODO: lock all array ranges before render, rather than on each surface
9422 if (texturenumsurfaces == 1)
9424 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9425 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);
9427 else if (r_batchmode.integer == 2)
9429 #define MAXBATCHTRIANGLES 4096
9430 int batchtriangles = 0;
9431 static int batchelements[MAXBATCHTRIANGLES*3];
9432 for (i = 0;i < texturenumsurfaces;i = j)
9434 surface = texturesurfacelist[i];
9436 if (surface->num_triangles > MAXBATCHTRIANGLES)
9438 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);
9441 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9442 batchtriangles = surface->num_triangles;
9443 firstvertex = surface->num_firstvertex;
9444 endvertex = surface->num_firstvertex + surface->num_vertices;
9445 for (;j < texturenumsurfaces;j++)
9447 surface2 = texturesurfacelist[j];
9448 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9450 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9451 batchtriangles += surface2->num_triangles;
9452 firstvertex = min(firstvertex, surface2->num_firstvertex);
9453 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9455 surface2 = texturesurfacelist[j-1];
9456 numvertices = endvertex - firstvertex;
9457 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9460 else if (r_batchmode.integer == 1)
9462 for (i = 0;i < texturenumsurfaces;i = j)
9464 surface = texturesurfacelist[i];
9465 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9466 if (texturesurfacelist[j] != surface2)
9468 surface2 = texturesurfacelist[j-1];
9469 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9470 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9471 GL_LockArrays(surface->num_firstvertex, numvertices);
9472 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9477 for (i = 0;i < texturenumsurfaces;i++)
9479 surface = texturesurfacelist[i];
9480 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9481 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);
9486 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9488 switch(vid.renderpath)
9490 case RENDERPATH_CGGL:
9492 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , R_GetTexture(surface->lightmaptexture ));CHECKCGERROR
9493 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, R_GetTexture(surface->deluxemaptexture));CHECKCGERROR
9496 case RENDERPATH_GL20:
9497 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(surface->lightmaptexture ));
9498 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, R_GetTexture(surface->deluxemaptexture));
9500 case RENDERPATH_GL13:
9501 case RENDERPATH_GL11:
9502 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
9507 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9509 // pick the closest matching water plane and bind textures
9510 int planeindex, vertexindex;
9514 r_waterstate_waterplane_t *p, *bestp;
9517 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9520 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9522 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9523 d += fabs(PlaneDiff(vert, &p->plane));
9525 if (bestd > d || !bestp)
9531 switch(vid.renderpath)
9533 case RENDERPATH_CGGL:
9535 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));CHECKCGERROR
9536 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));CHECKCGERROR
9539 case RENDERPATH_GL20:
9540 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));
9541 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));
9543 case RENDERPATH_GL13:
9544 case RENDERPATH_GL11:
9549 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9552 const msurface_t *surface;
9553 if (r_waterstate.renderingscene)
9555 for (i = 0;i < texturenumsurfaces;i++)
9557 surface = texturesurfacelist[i];
9558 RSurf_BindLightmapForSurface(surface);
9559 RSurf_BindReflectionForSurface(surface);
9560 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9561 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);
9565 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9569 const msurface_t *surface = texturesurfacelist[0];
9570 const msurface_t *surface2;
9575 if (texturenumsurfaces == 1)
9577 RSurf_BindLightmapForSurface(surface);
9578 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9579 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);
9581 else if (r_batchmode.integer == 2)
9583 #define MAXBATCHTRIANGLES 4096
9584 int batchtriangles = 0;
9585 static int batchelements[MAXBATCHTRIANGLES*3];
9586 for (i = 0;i < texturenumsurfaces;i = j)
9588 surface = texturesurfacelist[i];
9589 RSurf_BindLightmapForSurface(surface);
9591 if (surface->num_triangles > MAXBATCHTRIANGLES)
9593 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);
9596 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9597 batchtriangles = surface->num_triangles;
9598 firstvertex = surface->num_firstvertex;
9599 endvertex = surface->num_firstvertex + surface->num_vertices;
9600 for (;j < texturenumsurfaces;j++)
9602 surface2 = texturesurfacelist[j];
9603 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9605 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9606 batchtriangles += surface2->num_triangles;
9607 firstvertex = min(firstvertex, surface2->num_firstvertex);
9608 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9610 surface2 = texturesurfacelist[j-1];
9611 numvertices = endvertex - firstvertex;
9612 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9615 else if (r_batchmode.integer == 1)
9618 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9619 for (i = 0;i < texturenumsurfaces;i = j)
9621 surface = texturesurfacelist[i];
9622 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9623 if (texturesurfacelist[j] != surface2)
9625 Con_Printf(" %i", j - i);
9628 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9630 for (i = 0;i < texturenumsurfaces;i = j)
9632 surface = texturesurfacelist[i];
9633 RSurf_BindLightmapForSurface(surface);
9634 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9635 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9638 Con_Printf(" %i", j - i);
9640 surface2 = texturesurfacelist[j-1];
9641 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9642 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9643 GL_LockArrays(surface->num_firstvertex, numvertices);
9644 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9652 for (i = 0;i < texturenumsurfaces;i++)
9654 surface = texturesurfacelist[i];
9655 RSurf_BindLightmapForSurface(surface);
9656 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9657 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);
9662 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9665 int texturesurfaceindex;
9666 if (r_showsurfaces.integer == 2)
9668 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9670 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9671 for (j = 0;j < surface->num_triangles;j++)
9673 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9674 GL_Color(f, f, f, 1);
9675 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9681 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9683 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9684 int k = (int)(((size_t)surface) / sizeof(msurface_t));
9685 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);
9686 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9687 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);
9692 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9694 int texturesurfaceindex;
9698 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9700 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9701 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)
9709 rsurface.lightmapcolor4f = rsurface.array_color4f;
9710 rsurface.lightmapcolor4f_bufferobject = 0;
9711 rsurface.lightmapcolor4f_bufferoffset = 0;
9714 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9716 int texturesurfaceindex;
9722 if (rsurface.lightmapcolor4f)
9724 // generate color arrays for the surfaces in this list
9725 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9727 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9728 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)
9730 f = RSurf_FogVertex(v);
9740 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9742 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9743 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)
9745 f = RSurf_FogVertex(v);
9753 rsurface.lightmapcolor4f = rsurface.array_color4f;
9754 rsurface.lightmapcolor4f_bufferobject = 0;
9755 rsurface.lightmapcolor4f_bufferoffset = 0;
9758 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9760 int texturesurfaceindex;
9766 if (!rsurface.lightmapcolor4f)
9768 // generate color arrays for the surfaces in this list
9769 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9771 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9772 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)
9774 f = RSurf_FogVertex(v);
9775 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9776 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9777 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9781 rsurface.lightmapcolor4f = rsurface.array_color4f;
9782 rsurface.lightmapcolor4f_bufferobject = 0;
9783 rsurface.lightmapcolor4f_bufferoffset = 0;
9786 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
9788 int texturesurfaceindex;
9792 if (!rsurface.lightmapcolor4f)
9794 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9796 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9797 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)
9805 rsurface.lightmapcolor4f = rsurface.array_color4f;
9806 rsurface.lightmapcolor4f_bufferobject = 0;
9807 rsurface.lightmapcolor4f_bufferoffset = 0;
9810 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9812 int texturesurfaceindex;
9816 if (!rsurface.lightmapcolor4f)
9818 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9820 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9821 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)
9823 c2[0] = c[0] + r_refdef.scene.ambient;
9824 c2[1] = c[1] + r_refdef.scene.ambient;
9825 c2[2] = c[2] + r_refdef.scene.ambient;
9829 rsurface.lightmapcolor4f = rsurface.array_color4f;
9830 rsurface.lightmapcolor4f_bufferobject = 0;
9831 rsurface.lightmapcolor4f_bufferoffset = 0;
9834 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9837 rsurface.lightmapcolor4f = NULL;
9838 rsurface.lightmapcolor4f_bufferobject = 0;
9839 rsurface.lightmapcolor4f_bufferoffset = 0;
9840 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9841 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9842 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9843 GL_Color(r, g, b, a);
9844 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
9847 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9849 // TODO: optimize applyfog && applycolor case
9850 // just apply fog if necessary, and tint the fog color array if necessary
9851 rsurface.lightmapcolor4f = NULL;
9852 rsurface.lightmapcolor4f_bufferobject = 0;
9853 rsurface.lightmapcolor4f_bufferoffset = 0;
9854 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9855 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9856 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9857 GL_Color(r, g, b, a);
9858 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9861 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9863 int texturesurfaceindex;
9867 if (texturesurfacelist[0]->lightmapinfo)
9869 // generate color arrays for the surfaces in this list
9870 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9872 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9873 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
9875 if (surface->lightmapinfo->samples)
9877 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
9878 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
9879 VectorScale(lm, scale, c);
9880 if (surface->lightmapinfo->styles[1] != 255)
9882 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9884 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
9885 VectorMA(c, scale, lm, c);
9886 if (surface->lightmapinfo->styles[2] != 255)
9889 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
9890 VectorMA(c, scale, lm, c);
9891 if (surface->lightmapinfo->styles[3] != 255)
9894 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
9895 VectorMA(c, scale, lm, c);
9905 rsurface.lightmapcolor4f = rsurface.array_color4f;
9906 rsurface.lightmapcolor4f_bufferobject = 0;
9907 rsurface.lightmapcolor4f_bufferoffset = 0;
9911 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
9912 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
9913 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9915 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9916 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9917 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9918 GL_Color(r, g, b, a);
9919 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9922 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
9924 int texturesurfaceindex;
9931 vec3_t ambientcolor;
9932 vec3_t diffusecolor;
9936 VectorCopy(rsurface.modellight_lightdir, lightdir);
9937 f = 0.5f * r_refdef.lightmapintensity;
9938 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9939 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9940 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9941 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9942 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9943 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9945 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
9947 // generate color arrays for the surfaces in this list
9948 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9950 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9951 int numverts = surface->num_vertices;
9952 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
9953 n = rsurface.normal3f + 3 * surface->num_firstvertex;
9954 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
9955 // q3-style directional shading
9956 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
9958 if ((f = DotProduct(n, lightdir)) > 0)
9959 VectorMA(ambientcolor, f, diffusecolor, c);
9961 VectorCopy(ambientcolor, c);
9969 rsurface.lightmapcolor4f = rsurface.array_color4f;
9970 rsurface.lightmapcolor4f_bufferobject = 0;
9971 rsurface.lightmapcolor4f_bufferoffset = 0;
9972 *applycolor = false;
9976 *r = ambientcolor[0];
9977 *g = ambientcolor[1];
9978 *b = ambientcolor[2];
9979 rsurface.lightmapcolor4f = NULL;
9980 rsurface.lightmapcolor4f_bufferobject = 0;
9981 rsurface.lightmapcolor4f_bufferoffset = 0;
9985 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9987 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
9988 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9989 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9990 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9991 GL_Color(r, g, b, a);
9992 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9995 void RSurf_SetupDepthAndCulling(void)
9997 // submodels are biased to avoid z-fighting with world surfaces that they
9998 // may be exactly overlapping (avoids z-fighting artifacts on certain
9999 // doors and things in Quake maps)
10000 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10001 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10002 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10003 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10006 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10008 // transparent sky would be ridiculous
10009 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10011 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10012 skyrenderlater = true;
10013 RSurf_SetupDepthAndCulling();
10014 GL_DepthMask(true);
10015 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10016 // skymasking on them, and Quake3 never did sky masking (unlike
10017 // software Quake and software Quake2), so disable the sky masking
10018 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10019 // and skymasking also looks very bad when noclipping outside the
10020 // level, so don't use it then either.
10021 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10023 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10024 R_Mesh_ColorPointer(NULL, 0, 0);
10025 R_Mesh_ResetTextureState();
10026 if (skyrendermasked)
10028 R_SetupShader_DepthOrShadow();
10029 // depth-only (masking)
10030 GL_ColorMask(0,0,0,0);
10031 // just to make sure that braindead drivers don't draw
10032 // anything despite that colormask...
10033 GL_BlendFunc(GL_ZERO, GL_ONE);
10037 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10039 GL_BlendFunc(GL_ONE, GL_ZERO);
10041 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10042 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10043 if (skyrendermasked)
10044 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10046 R_Mesh_ResetTextureState();
10047 GL_Color(1, 1, 1, 1);
10050 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10051 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10052 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10054 qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
10055 qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
10057 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10060 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10061 R_Mesh_ColorPointer(NULL, 0, 0);
10063 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10067 // render background
10068 GL_BlendFunc(GL_ONE, GL_ZERO);
10069 GL_DepthMask(true);
10070 GL_AlphaTest(false);
10072 GL_Color(1, 1, 1, 1);
10073 R_Mesh_ColorPointer(NULL, 0, 0);
10075 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10076 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10077 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10078 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10079 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10080 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10081 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10082 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10083 GL_LockArrays(0, 0);
10085 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10086 GL_DepthMask(false);
10087 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10088 R_Mesh_ColorPointer(NULL, 0, 0);
10090 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10093 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10095 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10096 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10097 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10098 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10099 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10101 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10105 GL_BlendFunc(GL_ONE, GL_ZERO);
10106 GL_DepthMask(true);
10107 GL_AlphaTest(false);
10111 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10112 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10113 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
10116 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10118 if (refract || reflect)
10119 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10121 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10125 if (refract || reflect)
10126 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10128 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10130 GL_LockArrays(0, 0);
10133 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10135 // OpenGL 1.3 path - anything not completely ancient
10136 int texturesurfaceindex;
10137 qboolean applycolor;
10140 const texturelayer_t *layer;
10141 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10143 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10146 int layertexrgbscale;
10147 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10149 if (layerindex == 0)
10150 GL_AlphaTest(true);
10153 GL_AlphaTest(false);
10154 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10157 GL_DepthMask(layer->depthmask && writedepth);
10158 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10159 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10161 layertexrgbscale = 4;
10162 VectorScale(layer->color, 0.25f, layercolor);
10164 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10166 layertexrgbscale = 2;
10167 VectorScale(layer->color, 0.5f, layercolor);
10171 layertexrgbscale = 1;
10172 VectorScale(layer->color, 1.0f, layercolor);
10174 layercolor[3] = layer->color[3];
10175 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10176 R_Mesh_ColorPointer(NULL, 0, 0);
10177 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10178 switch (layer->type)
10180 case TEXTURELAYERTYPE_LITTEXTURE:
10181 // single-pass lightmapped texture with 2x rgbscale
10182 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
10183 R_Mesh_TexMatrix(0, NULL);
10184 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10185 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10186 R_Mesh_TexBind(1, R_GetTexture(layer->texture));
10187 R_Mesh_TexMatrix(1, &layer->texmatrix);
10188 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10189 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10190 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10191 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10192 else if (rsurface.uselightmaptexture)
10193 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10195 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10197 case TEXTURELAYERTYPE_TEXTURE:
10198 // singletexture unlit texture with transparency support
10199 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10200 R_Mesh_TexMatrix(0, &layer->texmatrix);
10201 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10202 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10203 R_Mesh_TexBind(1, 0);
10204 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10205 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10207 case TEXTURELAYERTYPE_FOG:
10208 // singletexture fogging
10209 if (layer->texture)
10211 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10212 R_Mesh_TexMatrix(0, &layer->texmatrix);
10213 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10214 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10218 R_Mesh_TexBind(0, 0);
10219 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10221 R_Mesh_TexBind(1, 0);
10222 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10223 // generate a color array for the fog pass
10224 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10225 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10231 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10232 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)
10234 f = 1 - RSurf_FogVertex(v);
10235 c[0] = layercolor[0];
10236 c[1] = layercolor[1];
10237 c[2] = layercolor[2];
10238 c[3] = f * layercolor[3];
10241 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10244 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10246 GL_LockArrays(0, 0);
10249 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10251 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10252 GL_AlphaTest(false);
10256 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10258 // OpenGL 1.1 - crusty old voodoo path
10259 int texturesurfaceindex;
10262 const texturelayer_t *layer;
10263 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10265 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10267 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10269 if (layerindex == 0)
10270 GL_AlphaTest(true);
10273 GL_AlphaTest(false);
10274 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10277 GL_DepthMask(layer->depthmask && writedepth);
10278 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10279 R_Mesh_ColorPointer(NULL, 0, 0);
10280 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10281 switch (layer->type)
10283 case TEXTURELAYERTYPE_LITTEXTURE:
10284 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10286 // two-pass lit texture with 2x rgbscale
10287 // first the lightmap pass
10288 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
10289 R_Mesh_TexMatrix(0, NULL);
10290 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10291 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10292 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10293 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10294 else if (rsurface.uselightmaptexture)
10295 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10297 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10298 GL_LockArrays(0, 0);
10299 // then apply the texture to it
10300 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10301 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10302 R_Mesh_TexMatrix(0, &layer->texmatrix);
10303 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10304 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10305 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);
10309 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10310 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10311 R_Mesh_TexMatrix(0, &layer->texmatrix);
10312 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10313 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10314 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10315 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);
10317 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);
10320 case TEXTURELAYERTYPE_TEXTURE:
10321 // singletexture unlit texture with transparency support
10322 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10323 R_Mesh_TexMatrix(0, &layer->texmatrix);
10324 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10325 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10326 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);
10328 case TEXTURELAYERTYPE_FOG:
10329 // singletexture fogging
10330 if (layer->texture)
10332 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10333 R_Mesh_TexMatrix(0, &layer->texmatrix);
10334 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10335 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10339 R_Mesh_TexBind(0, 0);
10340 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10342 // generate a color array for the fog pass
10343 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10344 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10350 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10351 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)
10353 f = 1 - RSurf_FogVertex(v);
10354 c[0] = layer->color[0];
10355 c[1] = layer->color[1];
10356 c[2] = layer->color[2];
10357 c[3] = f * layer->color[3];
10360 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10363 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10365 GL_LockArrays(0, 0);
10368 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10370 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10371 GL_AlphaTest(false);
10375 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10379 GL_AlphaTest(false);
10380 R_Mesh_ColorPointer(NULL, 0, 0);
10381 R_Mesh_ResetTextureState();
10382 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10384 if(rsurface.texture && rsurface.texture->currentskinframe)
10386 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10387 c[3] *= rsurface.texture->currentalpha;
10397 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10399 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10400 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10401 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10404 // brighten it up (as texture value 127 means "unlit")
10405 c[0] *= 2 * r_refdef.view.colorscale;
10406 c[1] *= 2 * r_refdef.view.colorscale;
10407 c[2] *= 2 * r_refdef.view.colorscale;
10409 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10410 c[3] *= r_wateralpha.value;
10412 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10414 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10415 GL_DepthMask(false);
10417 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10419 GL_BlendFunc(GL_ONE, GL_ONE);
10420 GL_DepthMask(false);
10422 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10424 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10425 GL_DepthMask(false);
10427 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10429 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10430 GL_DepthMask(false);
10434 GL_BlendFunc(GL_ONE, GL_ZERO);
10435 GL_DepthMask(writedepth);
10438 rsurface.lightmapcolor4f = NULL;
10440 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10442 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10444 rsurface.lightmapcolor4f = NULL;
10445 rsurface.lightmapcolor4f_bufferobject = 0;
10446 rsurface.lightmapcolor4f_bufferoffset = 0;
10448 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10450 qboolean applycolor = true;
10453 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10455 r_refdef.lightmapintensity = 1;
10456 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10457 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10461 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10463 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10464 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10465 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10468 if(!rsurface.lightmapcolor4f)
10469 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10471 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10472 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10473 if(r_refdef.fogenabled)
10474 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10476 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10477 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10480 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10483 RSurf_SetupDepthAndCulling();
10484 if (r_showsurfaces.integer == 3 && !prepass)
10486 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10489 switch (vid.renderpath)
10491 case RENDERPATH_GL20:
10492 case RENDERPATH_CGGL:
10493 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10495 case RENDERPATH_GL13:
10496 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10498 case RENDERPATH_GL11:
10499 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10505 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10508 RSurf_SetupDepthAndCulling();
10509 if (r_showsurfaces.integer == 3 && !prepass)
10511 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10514 switch (vid.renderpath)
10516 case RENDERPATH_GL20:
10517 case RENDERPATH_CGGL:
10518 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10520 case RENDERPATH_GL13:
10521 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10523 case RENDERPATH_GL11:
10524 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10530 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10533 int texturenumsurfaces, endsurface;
10534 texture_t *texture;
10535 const msurface_t *surface;
10536 const msurface_t *texturesurfacelist[256];
10538 // if the model is static it doesn't matter what value we give for
10539 // wantnormals and wanttangents, so this logic uses only rules applicable
10540 // to a model, knowing that they are meaningless otherwise
10541 if (ent == r_refdef.scene.worldentity)
10542 RSurf_ActiveWorldEntity();
10543 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10544 RSurf_ActiveModelEntity(ent, false, false, false);
10547 switch (vid.renderpath)
10549 case RENDERPATH_GL20:
10550 case RENDERPATH_CGGL:
10551 RSurf_ActiveModelEntity(ent, true, true, false);
10553 case RENDERPATH_GL13:
10554 case RENDERPATH_GL11:
10555 RSurf_ActiveModelEntity(ent, true, false, false);
10560 if (r_transparentdepthmasking.integer)
10562 qboolean setup = false;
10563 for (i = 0;i < numsurfaces;i = j)
10566 surface = rsurface.modelsurfaces + surfacelist[i];
10567 texture = surface->texture;
10568 rsurface.texture = R_GetCurrentTexture(texture);
10569 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10570 // scan ahead until we find a different texture
10571 endsurface = min(i + 1024, numsurfaces);
10572 texturenumsurfaces = 0;
10573 texturesurfacelist[texturenumsurfaces++] = surface;
10574 for (;j < endsurface;j++)
10576 surface = rsurface.modelsurfaces + surfacelist[j];
10577 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10579 texturesurfacelist[texturenumsurfaces++] = surface;
10581 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10583 // render the range of surfaces as depth
10587 GL_ColorMask(0,0,0,0);
10589 GL_DepthTest(true);
10590 GL_BlendFunc(GL_ONE, GL_ZERO);
10591 GL_DepthMask(true);
10592 GL_AlphaTest(false);
10593 R_Mesh_ColorPointer(NULL, 0, 0);
10594 R_Mesh_ResetTextureState();
10595 R_SetupShader_DepthOrShadow();
10597 RSurf_SetupDepthAndCulling();
10598 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10599 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10602 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10605 for (i = 0;i < numsurfaces;i = j)
10608 surface = rsurface.modelsurfaces + surfacelist[i];
10609 texture = surface->texture;
10610 rsurface.texture = R_GetCurrentTexture(texture);
10611 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10612 // scan ahead until we find a different texture
10613 endsurface = min(i + 1024, numsurfaces);
10614 texturenumsurfaces = 0;
10615 texturesurfacelist[texturenumsurfaces++] = surface;
10616 for (;j < endsurface;j++)
10618 surface = rsurface.modelsurfaces + surfacelist[j];
10619 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10621 texturesurfacelist[texturenumsurfaces++] = surface;
10623 // render the range of surfaces
10624 if (ent == r_refdef.scene.worldentity)
10625 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10627 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10629 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10630 GL_AlphaTest(false);
10633 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10635 // transparent surfaces get pushed off into the transparent queue
10636 int surfacelistindex;
10637 const msurface_t *surface;
10638 vec3_t tempcenter, center;
10639 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10641 surface = texturesurfacelist[surfacelistindex];
10642 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10643 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10644 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10645 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10646 if (queueentity->transparent_offset) // transparent offset
10648 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10649 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10650 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10652 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10656 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10658 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10662 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10664 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10666 RSurf_SetupDepthAndCulling();
10667 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10668 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10672 if (!rsurface.texture->currentnumlayers)
10674 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10675 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10677 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10679 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10681 RSurf_SetupDepthAndCulling();
10682 GL_AlphaTest(false);
10683 R_Mesh_ColorPointer(NULL, 0, 0);
10684 R_Mesh_ResetTextureState();
10685 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10686 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10687 GL_DepthMask(true);
10688 GL_BlendFunc(GL_ONE, GL_ZERO);
10689 GL_Color(0, 0, 0, 1);
10690 GL_DepthTest(writedepth);
10691 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10693 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10695 RSurf_SetupDepthAndCulling();
10696 GL_AlphaTest(false);
10697 R_Mesh_ColorPointer(NULL, 0, 0);
10698 R_Mesh_ResetTextureState();
10699 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10700 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10701 GL_DepthMask(true);
10702 GL_BlendFunc(GL_ONE, GL_ZERO);
10703 GL_DepthTest(true);
10704 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10706 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10707 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10708 else if (!rsurface.texture->currentnumlayers)
10710 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10712 // in the deferred case, transparent surfaces were queued during prepass
10713 if (!r_shadow_usingdeferredprepass)
10714 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10718 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10719 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10724 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10727 texture_t *texture;
10728 // break the surface list down into batches by texture and use of lightmapping
10729 for (i = 0;i < numsurfaces;i = j)
10732 // texture is the base texture pointer, rsurface.texture is the
10733 // current frame/skin the texture is directing us to use (for example
10734 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10735 // use skin 1 instead)
10736 texture = surfacelist[i]->texture;
10737 rsurface.texture = R_GetCurrentTexture(texture);
10738 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10739 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10741 // if this texture is not the kind we want, skip ahead to the next one
10742 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10746 // simply scan ahead until we find a different texture or lightmap state
10747 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10749 // render the range of surfaces
10750 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10754 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10759 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10761 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10763 RSurf_SetupDepthAndCulling();
10764 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10765 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10769 if (!rsurface.texture->currentnumlayers)
10771 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10772 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10774 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10776 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10778 RSurf_SetupDepthAndCulling();
10779 GL_AlphaTest(false);
10780 R_Mesh_ColorPointer(NULL, 0, 0);
10781 R_Mesh_ResetTextureState();
10782 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10783 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10784 GL_DepthMask(true);
10785 GL_BlendFunc(GL_ONE, GL_ZERO);
10786 GL_Color(0, 0, 0, 1);
10787 GL_DepthTest(writedepth);
10788 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10790 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10792 RSurf_SetupDepthAndCulling();
10793 GL_AlphaTest(false);
10794 R_Mesh_ColorPointer(NULL, 0, 0);
10795 R_Mesh_ResetTextureState();
10796 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10797 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10798 GL_DepthMask(true);
10799 GL_BlendFunc(GL_ONE, GL_ZERO);
10800 GL_DepthTest(true);
10801 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10803 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10804 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10805 else if (!rsurface.texture->currentnumlayers)
10807 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10809 // in the deferred case, transparent surfaces were queued during prepass
10810 if (!r_shadow_usingdeferredprepass)
10811 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10815 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10816 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10821 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10824 texture_t *texture;
10825 // break the surface list down into batches by texture and use of lightmapping
10826 for (i = 0;i < numsurfaces;i = j)
10829 // texture is the base texture pointer, rsurface.texture is the
10830 // current frame/skin the texture is directing us to use (for example
10831 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10832 // use skin 1 instead)
10833 texture = surfacelist[i]->texture;
10834 rsurface.texture = R_GetCurrentTexture(texture);
10835 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10836 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10838 // if this texture is not the kind we want, skip ahead to the next one
10839 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10843 // simply scan ahead until we find a different texture or lightmap state
10844 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10846 // render the range of surfaces
10847 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10851 float locboxvertex3f[6*4*3] =
10853 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10854 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10855 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10856 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10857 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10858 1,0,0, 0,0,0, 0,1,0, 1,1,0
10861 unsigned short locboxelements[6*2*3] =
10866 12,13,14, 12,14,15,
10867 16,17,18, 16,18,19,
10871 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10874 cl_locnode_t *loc = (cl_locnode_t *)ent;
10876 float vertex3f[6*4*3];
10878 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10879 GL_DepthMask(false);
10880 GL_DepthRange(0, 1);
10881 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10882 GL_DepthTest(true);
10883 GL_CullFace(GL_NONE);
10884 R_EntityMatrix(&identitymatrix);
10886 R_Mesh_VertexPointer(vertex3f, 0, 0);
10887 R_Mesh_ColorPointer(NULL, 0, 0);
10888 R_Mesh_ResetTextureState();
10889 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10891 i = surfacelist[0];
10892 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10893 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10894 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10895 surfacelist[0] < 0 ? 0.5f : 0.125f);
10897 if (VectorCompare(loc->mins, loc->maxs))
10899 VectorSet(size, 2, 2, 2);
10900 VectorMA(loc->mins, -0.5f, size, mins);
10904 VectorCopy(loc->mins, mins);
10905 VectorSubtract(loc->maxs, loc->mins, size);
10908 for (i = 0;i < 6*4*3;)
10909 for (j = 0;j < 3;j++, i++)
10910 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10912 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
10915 void R_DrawLocs(void)
10918 cl_locnode_t *loc, *nearestloc;
10920 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10921 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10923 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10924 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10928 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10930 if (decalsystem->decals)
10931 Mem_Free(decalsystem->decals);
10932 memset(decalsystem, 0, sizeof(*decalsystem));
10935 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)
10938 tridecal_t *decals;
10942 // expand or initialize the system
10943 if (decalsystem->maxdecals <= decalsystem->numdecals)
10945 decalsystem_t old = *decalsystem;
10946 qboolean useshortelements;
10947 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10948 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10949 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)));
10950 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10951 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10952 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10953 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10954 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10955 if (decalsystem->numdecals)
10956 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10958 Mem_Free(old.decals);
10959 for (i = 0;i < decalsystem->maxdecals*3;i++)
10960 decalsystem->element3i[i] = i;
10961 if (useshortelements)
10962 for (i = 0;i < decalsystem->maxdecals*3;i++)
10963 decalsystem->element3s[i] = i;
10966 // grab a decal and search for another free slot for the next one
10967 maxdecals = decalsystem->maxdecals;
10968 decals = decalsystem->decals;
10969 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10970 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
10972 decalsystem->freedecal = i;
10973 if (decalsystem->numdecals <= i)
10974 decalsystem->numdecals = i + 1;
10976 // initialize the decal
10978 decal->triangleindex = triangleindex;
10979 decal->surfaceindex = surfaceindex;
10980 decal->decalsequence = decalsequence;
10981 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
10982 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
10983 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
10984 decal->color4ub[0][3] = 255;
10985 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
10986 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
10987 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
10988 decal->color4ub[1][3] = 255;
10989 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
10990 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
10991 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
10992 decal->color4ub[2][3] = 255;
10993 decal->vertex3f[0][0] = v0[0];
10994 decal->vertex3f[0][1] = v0[1];
10995 decal->vertex3f[0][2] = v0[2];
10996 decal->vertex3f[1][0] = v1[0];
10997 decal->vertex3f[1][1] = v1[1];
10998 decal->vertex3f[1][2] = v1[2];
10999 decal->vertex3f[2][0] = v2[0];
11000 decal->vertex3f[2][1] = v2[1];
11001 decal->vertex3f[2][2] = v2[2];
11002 decal->texcoord2f[0][0] = t0[0];
11003 decal->texcoord2f[0][1] = t0[1];
11004 decal->texcoord2f[1][0] = t1[0];
11005 decal->texcoord2f[1][1] = t1[1];
11006 decal->texcoord2f[2][0] = t2[0];
11007 decal->texcoord2f[2][1] = t2[1];
11010 extern cvar_t cl_decals_bias;
11011 extern cvar_t cl_decals_models;
11012 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11013 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)
11015 matrix4x4_t projection;
11016 decalsystem_t *decalsystem;
11019 const float *vertex3f;
11020 const msurface_t *surface;
11021 const msurface_t *surfaces;
11022 const int *surfacelist;
11023 const texture_t *texture;
11026 int numsurfacelist;
11027 int surfacelistindex;
11030 int decalsurfaceindex;
11035 float localorigin[3];
11036 float localnormal[3];
11037 float localmins[3];
11038 float localmaxs[3];
11045 float planes[6][4];
11047 float points[2][9][3];
11051 decalsystem = &ent->decalsystem;
11052 model = ent->model;
11053 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11055 R_DecalSystem_Reset(&ent->decalsystem);
11059 if (!model->brush.data_nodes && !cl_decals_models.integer)
11061 if (decalsystem->model)
11062 R_DecalSystem_Reset(decalsystem);
11066 if (decalsystem->model != model)
11067 R_DecalSystem_Reset(decalsystem);
11068 decalsystem->model = model;
11070 RSurf_ActiveModelEntity(ent, false, false, false);
11072 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11073 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11074 VectorNormalize(localnormal);
11075 localsize = worldsize*rsurface.inversematrixscale;
11076 ilocalsize = 1.0f / localsize;
11077 localmins[0] = localorigin[0] - localsize;
11078 localmins[1] = localorigin[1] - localsize;
11079 localmins[2] = localorigin[2] - localsize;
11080 localmaxs[0] = localorigin[0] + localsize;
11081 localmaxs[1] = localorigin[1] + localsize;
11082 localmaxs[2] = localorigin[2] + localsize;
11084 //VectorCopy(localnormal, planes[4]);
11085 //VectorVectors(planes[4], planes[2], planes[0]);
11086 AnglesFromVectors(angles, localnormal, NULL, false);
11087 AngleVectors(angles, planes[0], planes[2], planes[4]);
11088 VectorNegate(planes[0], planes[1]);
11089 VectorNegate(planes[2], planes[3]);
11090 VectorNegate(planes[4], planes[5]);
11091 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11092 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11093 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11094 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11095 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11096 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11101 matrix4x4_t forwardprojection;
11102 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11103 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11108 float projectionvector[4][3];
11109 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11110 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11111 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11112 projectionvector[0][0] = planes[0][0] * ilocalsize;
11113 projectionvector[0][1] = planes[1][0] * ilocalsize;
11114 projectionvector[0][2] = planes[2][0] * ilocalsize;
11115 projectionvector[1][0] = planes[0][1] * ilocalsize;
11116 projectionvector[1][1] = planes[1][1] * ilocalsize;
11117 projectionvector[1][2] = planes[2][1] * ilocalsize;
11118 projectionvector[2][0] = planes[0][2] * ilocalsize;
11119 projectionvector[2][1] = planes[1][2] * ilocalsize;
11120 projectionvector[2][2] = planes[2][2] * ilocalsize;
11121 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11122 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11123 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11124 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11128 dynamic = model->surfmesh.isanimated;
11129 vertex3f = rsurface.modelvertex3f;
11130 numsurfacelist = model->nummodelsurfaces;
11131 surfacelist = model->sortedmodelsurfaces;
11132 surfaces = model->data_surfaces;
11133 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11135 surfaceindex = surfacelist[surfacelistindex];
11136 surface = surfaces + surfaceindex;
11137 // skip transparent surfaces
11138 texture = surface->texture;
11139 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11141 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11143 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11145 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11146 numvertices = surface->num_vertices;
11147 numtriangles = surface->num_triangles;
11148 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11150 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11152 index = 3*e[cornerindex];
11153 VectorCopy(vertex3f + index, v[cornerindex]);
11156 //TriangleNormal(v[0], v[1], v[2], normal);
11157 //if (DotProduct(normal, localnormal) < 0.0f)
11159 // clip by each of the box planes formed from the projection matrix
11160 // if anything survives, we emit the decal
11161 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]);
11164 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]);
11167 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]);
11170 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]);
11173 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]);
11176 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]);
11179 // some part of the triangle survived, so we have to accept it...
11182 // dynamic always uses the original triangle
11184 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11186 index = 3*e[cornerindex];
11187 VectorCopy(vertex3f + index, v[cornerindex]);
11190 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11192 // convert vertex positions to texcoords
11193 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11194 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11195 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11196 // calculate distance fade from the projection origin
11197 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11198 f = bound(0.0f, f, 1.0f);
11199 c[cornerindex][0] = r * f;
11200 c[cornerindex][1] = g * f;
11201 c[cornerindex][2] = b * f;
11202 c[cornerindex][3] = 1.0f;
11203 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11206 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);
11208 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11209 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);
11214 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11215 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)
11217 int renderentityindex;
11218 float worldmins[3];
11219 float worldmaxs[3];
11220 entity_render_t *ent;
11222 if (!cl_decals_newsystem.integer)
11225 worldmins[0] = worldorigin[0] - worldsize;
11226 worldmins[1] = worldorigin[1] - worldsize;
11227 worldmins[2] = worldorigin[2] - worldsize;
11228 worldmaxs[0] = worldorigin[0] + worldsize;
11229 worldmaxs[1] = worldorigin[1] + worldsize;
11230 worldmaxs[2] = worldorigin[2] + worldsize;
11232 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11234 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11236 ent = r_refdef.scene.entities[renderentityindex];
11237 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11240 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11244 typedef struct r_decalsystem_splatqueue_s
11246 vec3_t worldorigin;
11247 vec3_t worldnormal;
11253 r_decalsystem_splatqueue_t;
11255 int r_decalsystem_numqueued = 0;
11256 #define MAX_DECALSYSTEM_QUEUE 1024
11257 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11259 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)
11261 r_decalsystem_splatqueue_t *queue;
11263 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11266 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11267 VectorCopy(worldorigin, queue->worldorigin);
11268 VectorCopy(worldnormal, queue->worldnormal);
11269 Vector4Set(queue->color, r, g, b, a);
11270 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11271 queue->worldsize = worldsize;
11272 queue->decalsequence = cl.decalsequence++;
11275 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11278 r_decalsystem_splatqueue_t *queue;
11280 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11281 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);
11282 r_decalsystem_numqueued = 0;
11285 extern cvar_t cl_decals_max;
11286 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11289 decalsystem_t *decalsystem = &ent->decalsystem;
11296 if (!decalsystem->numdecals)
11299 if (r_showsurfaces.integer)
11302 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11304 R_DecalSystem_Reset(decalsystem);
11308 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11309 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11311 if (decalsystem->lastupdatetime)
11312 frametime = (cl.time - decalsystem->lastupdatetime);
11315 decalsystem->lastupdatetime = cl.time;
11316 decal = decalsystem->decals;
11317 numdecals = decalsystem->numdecals;
11319 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11321 if (decal->color4ub[0][3])
11323 decal->lived += frametime;
11324 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11326 memset(decal, 0, sizeof(*decal));
11327 if (decalsystem->freedecal > i)
11328 decalsystem->freedecal = i;
11332 decal = decalsystem->decals;
11333 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11336 // collapse the array by shuffling the tail decals into the gaps
11339 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11340 decalsystem->freedecal++;
11341 if (decalsystem->freedecal == numdecals)
11343 decal[decalsystem->freedecal] = decal[--numdecals];
11346 decalsystem->numdecals = numdecals;
11348 if (numdecals <= 0)
11350 // if there are no decals left, reset decalsystem
11351 R_DecalSystem_Reset(decalsystem);
11355 extern skinframe_t *decalskinframe;
11356 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11359 decalsystem_t *decalsystem = &ent->decalsystem;
11369 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11372 numdecals = decalsystem->numdecals;
11376 if (r_showsurfaces.integer)
11379 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11381 R_DecalSystem_Reset(decalsystem);
11385 // if the model is static it doesn't matter what value we give for
11386 // wantnormals and wanttangents, so this logic uses only rules applicable
11387 // to a model, knowing that they are meaningless otherwise
11388 if (ent == r_refdef.scene.worldentity)
11389 RSurf_ActiveWorldEntity();
11391 RSurf_ActiveModelEntity(ent, false, false, false);
11393 decalsystem->lastupdatetime = cl.time;
11394 decal = decalsystem->decals;
11396 fadedelay = cl_decals_time.value;
11397 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11399 // update vertex positions for animated models
11400 v3f = decalsystem->vertex3f;
11401 c4f = decalsystem->color4f;
11402 t2f = decalsystem->texcoord2f;
11403 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11405 if (!decal->color4ub[0][3])
11408 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11411 // update color values for fading decals
11412 if (decal->lived >= cl_decals_time.value)
11414 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11415 alpha *= (1.0f/255.0f);
11418 alpha = 1.0f/255.0f;
11420 c4f[ 0] = decal->color4ub[0][0] * alpha;
11421 c4f[ 1] = decal->color4ub[0][1] * alpha;
11422 c4f[ 2] = decal->color4ub[0][2] * alpha;
11424 c4f[ 4] = decal->color4ub[1][0] * alpha;
11425 c4f[ 5] = decal->color4ub[1][1] * alpha;
11426 c4f[ 6] = decal->color4ub[1][2] * alpha;
11428 c4f[ 8] = decal->color4ub[2][0] * alpha;
11429 c4f[ 9] = decal->color4ub[2][1] * alpha;
11430 c4f[10] = decal->color4ub[2][2] * alpha;
11433 t2f[0] = decal->texcoord2f[0][0];
11434 t2f[1] = decal->texcoord2f[0][1];
11435 t2f[2] = decal->texcoord2f[1][0];
11436 t2f[3] = decal->texcoord2f[1][1];
11437 t2f[4] = decal->texcoord2f[2][0];
11438 t2f[5] = decal->texcoord2f[2][1];
11440 // update vertex positions for animated models
11441 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11443 e = rsurface.modelelement3i + 3*decal->triangleindex;
11444 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11445 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11446 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11450 VectorCopy(decal->vertex3f[0], v3f);
11451 VectorCopy(decal->vertex3f[1], v3f + 3);
11452 VectorCopy(decal->vertex3f[2], v3f + 6);
11463 r_refdef.stats.drawndecals += numtris;
11465 if (r_refdef.fogenabled)
11467 switch(vid.renderpath)
11469 case RENDERPATH_GL20:
11470 case RENDERPATH_CGGL:
11471 case RENDERPATH_GL13:
11472 case RENDERPATH_GL11:
11473 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11475 alpha = RSurf_FogVertex(v3f);
11484 // now render the decals all at once
11485 // (this assumes they all use one particle font texture!)
11486 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);
11487 R_Mesh_ResetTextureState();
11488 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11489 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11490 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11491 GL_DepthMask(false);
11492 GL_DepthRange(0, 1);
11493 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11494 GL_DepthTest(true);
11495 GL_CullFace(GL_NONE);
11496 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11497 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11498 GL_LockArrays(0, numtris * 3);
11499 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11500 GL_LockArrays(0, 0);
11504 static void R_DrawModelDecals(void)
11508 // fade faster when there are too many decals
11509 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11510 for (i = 0;i < r_refdef.scene.numentities;i++)
11511 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11513 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11514 for (i = 0;i < r_refdef.scene.numentities;i++)
11515 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11516 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11518 R_DecalSystem_ApplySplatEntitiesQueue();
11520 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11521 for (i = 0;i < r_refdef.scene.numentities;i++)
11522 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11524 r_refdef.stats.totaldecals += numdecals;
11526 if (r_showsurfaces.integer)
11529 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11531 for (i = 0;i < r_refdef.scene.numentities;i++)
11533 if (!r_refdef.viewcache.entityvisible[i])
11535 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11536 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11540 void R_DrawDebugModel(void)
11542 entity_render_t *ent = rsurface.entity;
11543 int i, j, k, l, flagsmask;
11544 const int *elements;
11546 const msurface_t *surface;
11547 dp_model_t *model = ent->model;
11550 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11552 R_Mesh_ColorPointer(NULL, 0, 0);
11553 R_Mesh_ResetTextureState();
11554 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11555 GL_DepthRange(0, 1);
11556 GL_DepthTest(!r_showdisabledepthtest.integer);
11557 GL_DepthMask(false);
11558 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11560 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11562 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11563 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11565 if (brush->colbrushf && brush->colbrushf->numtriangles)
11567 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11568 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);
11569 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11572 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11574 if (surface->num_collisiontriangles)
11576 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11577 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);
11578 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11583 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11585 if (r_showtris.integer || r_shownormals.integer)
11587 if (r_showdisabledepthtest.integer)
11589 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11590 GL_DepthMask(false);
11594 GL_BlendFunc(GL_ONE, GL_ZERO);
11595 GL_DepthMask(true);
11597 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11599 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11601 rsurface.texture = R_GetCurrentTexture(surface->texture);
11602 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11604 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11605 if (r_showtris.value > 0)
11607 if (!rsurface.texture->currentlayers->depthmask)
11608 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11609 else if (ent == r_refdef.scene.worldentity)
11610 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11612 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11613 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11614 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11615 R_Mesh_ColorPointer(NULL, 0, 0);
11616 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11617 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11618 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11619 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);
11620 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11623 if (r_shownormals.value < 0)
11625 qglBegin(GL_LINES);
11626 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11628 VectorCopy(rsurface.vertex3f + l * 3, v);
11629 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11630 qglVertex3f(v[0], v[1], v[2]);
11631 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11632 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11633 qglVertex3f(v[0], v[1], v[2]);
11638 if (r_shownormals.value > 0)
11640 qglBegin(GL_LINES);
11641 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11643 VectorCopy(rsurface.vertex3f + l * 3, v);
11644 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11645 qglVertex3f(v[0], v[1], v[2]);
11646 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11647 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11648 qglVertex3f(v[0], v[1], v[2]);
11652 qglBegin(GL_LINES);
11653 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11655 VectorCopy(rsurface.vertex3f + l * 3, v);
11656 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11657 qglVertex3f(v[0], v[1], v[2]);
11658 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11659 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11660 qglVertex3f(v[0], v[1], v[2]);
11664 qglBegin(GL_LINES);
11665 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11667 VectorCopy(rsurface.vertex3f + l * 3, v);
11668 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11669 qglVertex3f(v[0], v[1], v[2]);
11670 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11671 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11672 qglVertex3f(v[0], v[1], v[2]);
11679 rsurface.texture = NULL;
11683 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11684 int r_maxsurfacelist = 0;
11685 const msurface_t **r_surfacelist = NULL;
11686 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11688 int i, j, endj, f, flagsmask;
11690 dp_model_t *model = r_refdef.scene.worldmodel;
11691 msurface_t *surfaces;
11692 unsigned char *update;
11693 int numsurfacelist = 0;
11697 if (r_maxsurfacelist < model->num_surfaces)
11699 r_maxsurfacelist = model->num_surfaces;
11701 Mem_Free((msurface_t**)r_surfacelist);
11702 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11705 RSurf_ActiveWorldEntity();
11707 surfaces = model->data_surfaces;
11708 update = model->brushq1.lightmapupdateflags;
11710 // update light styles on this submodel
11711 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11713 model_brush_lightstyleinfo_t *style;
11714 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11716 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11718 int *list = style->surfacelist;
11719 style->value = r_refdef.scene.lightstylevalue[style->style];
11720 for (j = 0;j < style->numsurfaces;j++)
11721 update[list[j]] = true;
11726 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11730 R_DrawDebugModel();
11731 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11737 rsurface.uselightmaptexture = false;
11738 rsurface.texture = NULL;
11739 rsurface.rtlight = NULL;
11740 numsurfacelist = 0;
11741 // add visible surfaces to draw list
11742 for (i = 0;i < model->nummodelsurfaces;i++)
11744 j = model->sortedmodelsurfaces[i];
11745 if (r_refdef.viewcache.world_surfacevisible[j])
11746 r_surfacelist[numsurfacelist++] = surfaces + j;
11748 // update lightmaps if needed
11752 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11754 if (r_refdef.viewcache.world_surfacevisible[j])
11759 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11765 int count = model->brushq3.num_mergedlightmaps;
11766 for (i = 0;i < count;i++)
11768 if (model->brushq3.data_deluxemaps[i])
11769 R_FlushTexture(model->brushq3.data_deluxemaps[i]);
11770 if (model->brushq3.data_lightmaps[i])
11771 R_FlushTexture(model->brushq3.data_lightmaps[i]);
11775 // don't do anything if there were no surfaces
11776 if (!numsurfacelist)
11778 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11781 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11782 GL_AlphaTest(false);
11784 // add to stats if desired
11785 if (r_speeds.integer && !skysurfaces && !depthonly)
11787 r_refdef.stats.world_surfaces += numsurfacelist;
11788 for (j = 0;j < numsurfacelist;j++)
11789 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11792 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11795 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11797 int i, j, endj, f, flagsmask;
11799 dp_model_t *model = ent->model;
11800 msurface_t *surfaces;
11801 unsigned char *update;
11802 int numsurfacelist = 0;
11806 if (r_maxsurfacelist < model->num_surfaces)
11808 r_maxsurfacelist = model->num_surfaces;
11810 Mem_Free((msurface_t **)r_surfacelist);
11811 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11814 // if the model is static it doesn't matter what value we give for
11815 // wantnormals and wanttangents, so this logic uses only rules applicable
11816 // to a model, knowing that they are meaningless otherwise
11817 if (ent == r_refdef.scene.worldentity)
11818 RSurf_ActiveWorldEntity();
11819 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11820 RSurf_ActiveModelEntity(ent, false, false, false);
11822 RSurf_ActiveModelEntity(ent, true, true, true);
11823 else if (depthonly)
11824 RSurf_ActiveModelEntity(ent, false, false, false);
11827 switch (vid.renderpath)
11829 case RENDERPATH_GL20:
11830 case RENDERPATH_CGGL:
11831 RSurf_ActiveModelEntity(ent, true, true, false);
11833 case RENDERPATH_GL13:
11834 case RENDERPATH_GL11:
11835 RSurf_ActiveModelEntity(ent, true, false, false);
11840 surfaces = model->data_surfaces;
11841 update = model->brushq1.lightmapupdateflags;
11843 // update light styles
11844 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11846 model_brush_lightstyleinfo_t *style;
11847 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11849 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11851 int *list = style->surfacelist;
11852 style->value = r_refdef.scene.lightstylevalue[style->style];
11853 for (j = 0;j < style->numsurfaces;j++)
11854 update[list[j]] = true;
11859 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11863 R_DrawDebugModel();
11864 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11870 rsurface.uselightmaptexture = false;
11871 rsurface.texture = NULL;
11872 rsurface.rtlight = NULL;
11873 numsurfacelist = 0;
11874 // add visible surfaces to draw list
11875 for (i = 0;i < model->nummodelsurfaces;i++)
11876 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11877 // don't do anything if there were no surfaces
11878 if (!numsurfacelist)
11880 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11883 // update lightmaps if needed
11887 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11892 R_BuildLightMap(ent, surfaces + j);
11897 int count = model->brushq3.num_mergedlightmaps;
11898 for (i = 0;i < count;i++)
11900 if (model->brushq3.data_deluxemaps[i])
11901 R_FlushTexture(model->brushq3.data_deluxemaps[i]);
11902 if (model->brushq3.data_lightmaps[i])
11903 R_FlushTexture(model->brushq3.data_lightmaps[i]);
11908 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11910 R_BuildLightMap(ent, surfaces + j);
11911 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11912 GL_AlphaTest(false);
11914 // add to stats if desired
11915 if (r_speeds.integer && !skysurfaces && !depthonly)
11917 r_refdef.stats.entities_surfaces += numsurfacelist;
11918 for (j = 0;j < numsurfacelist;j++)
11919 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11922 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11925 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11927 static texture_t texture;
11928 static msurface_t surface;
11929 const msurface_t *surfacelist = &surface;
11931 // fake enough texture and surface state to render this geometry
11933 texture.update_lastrenderframe = -1; // regenerate this texture
11934 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11935 texture.currentskinframe = skinframe;
11936 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11937 texture.specularscalemod = 1;
11938 texture.specularpowermod = 1;
11940 surface.texture = &texture;
11941 surface.num_triangles = numtriangles;
11942 surface.num_firsttriangle = firsttriangle;
11943 surface.num_vertices = numvertices;
11944 surface.num_firstvertex = firstvertex;
11947 rsurface.texture = R_GetCurrentTexture(surface.texture);
11948 rsurface.uselightmaptexture = false;
11949 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11952 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)
11954 static msurface_t surface;
11955 const msurface_t *surfacelist = &surface;
11957 // fake enough texture and surface state to render this geometry
11959 surface.texture = texture;
11960 surface.num_triangles = numtriangles;
11961 surface.num_firsttriangle = firsttriangle;
11962 surface.num_vertices = numvertices;
11963 surface.num_firstvertex = firstvertex;
11966 rsurface.texture = R_GetCurrentTexture(surface.texture);
11967 rsurface.uselightmaptexture = false;
11968 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);