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_extra.integer)
421 Con_DPrintf("%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_extra.integer)
428 Con_DPrintf(" : %f ", alpha);
429 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
430 if(developer_extra.integer)
431 Con_DPrintf(" = %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 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3577 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3581 Mem_Free(vertexstring);
3583 Mem_Free(geometrystring);
3585 Mem_Free(fragmentstring);
3588 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3590 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3591 if (r_glsl_permutation != perm)
3593 r_glsl_permutation = perm;
3594 if (!r_glsl_permutation->program)
3596 if (!r_glsl_permutation->compiled)
3597 R_GLSL_CompilePermutation(perm, mode, permutation);
3598 if (!r_glsl_permutation->program)
3600 // remove features until we find a valid permutation
3602 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3604 // reduce i more quickly whenever it would not remove any bits
3605 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3606 if (!(permutation & j))
3609 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3610 if (!r_glsl_permutation->compiled)
3611 R_GLSL_CompilePermutation(perm, mode, permutation);
3612 if (r_glsl_permutation->program)
3615 if (i >= SHADERPERMUTATION_COUNT)
3617 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3618 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3619 qglUseProgramObjectARB(0);CHECKGLERROR
3620 return; // no bit left to clear, entire mode is broken
3625 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3627 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3631 #include <Cg/cgGL.h>
3632 struct r_cg_permutation_s;
3633 typedef struct r_cg_permutation_s
3635 /// hash lookup data
3636 struct r_cg_permutation_s *hashnext;
3638 unsigned int permutation;
3640 /// indicates if we have tried compiling this permutation already
3642 /// 0 if compilation failed
3645 /// locations of detected parameters in programs, or NULL if not found
3646 CGparameter vp_EyePosition;
3647 CGparameter vp_FogPlane;
3648 CGparameter vp_LightDir;
3649 CGparameter vp_LightPosition;
3650 CGparameter vp_ModelToLight;
3651 CGparameter vp_TexMatrix;
3652 CGparameter vp_BackgroundTexMatrix;
3653 CGparameter vp_ModelViewProjectionMatrix;
3654 CGparameter vp_ModelViewMatrix;
3656 CGparameter fp_Texture_First;
3657 CGparameter fp_Texture_Second;
3658 CGparameter fp_Texture_GammaRamps;
3659 CGparameter fp_Texture_Normal;
3660 CGparameter fp_Texture_Color;
3661 CGparameter fp_Texture_Gloss;
3662 CGparameter fp_Texture_Glow;
3663 CGparameter fp_Texture_SecondaryNormal;
3664 CGparameter fp_Texture_SecondaryColor;
3665 CGparameter fp_Texture_SecondaryGloss;
3666 CGparameter fp_Texture_SecondaryGlow;
3667 CGparameter fp_Texture_Pants;
3668 CGparameter fp_Texture_Shirt;
3669 CGparameter fp_Texture_FogMask;
3670 CGparameter fp_Texture_Lightmap;
3671 CGparameter fp_Texture_Deluxemap;
3672 CGparameter fp_Texture_Attenuation;
3673 CGparameter fp_Texture_Cube;
3674 CGparameter fp_Texture_Refraction;
3675 CGparameter fp_Texture_Reflection;
3676 CGparameter fp_Texture_ShadowMapRect;
3677 CGparameter fp_Texture_ShadowMapCube;
3678 CGparameter fp_Texture_ShadowMap2D;
3679 CGparameter fp_Texture_CubeProjection;
3680 CGparameter fp_Texture_ScreenDepth;
3681 CGparameter fp_Texture_ScreenNormalMap;
3682 CGparameter fp_Texture_ScreenDiffuse;
3683 CGparameter fp_Texture_ScreenSpecular;
3684 CGparameter fp_Alpha;
3685 CGparameter fp_BloomBlur_Parameters;
3686 CGparameter fp_ClientTime;
3687 CGparameter fp_Color_Ambient;
3688 CGparameter fp_Color_Diffuse;
3689 CGparameter fp_Color_Specular;
3690 CGparameter fp_Color_Glow;
3691 CGparameter fp_Color_Pants;
3692 CGparameter fp_Color_Shirt;
3693 CGparameter fp_DeferredColor_Ambient;
3694 CGparameter fp_DeferredColor_Diffuse;
3695 CGparameter fp_DeferredColor_Specular;
3696 CGparameter fp_DeferredMod_Diffuse;
3697 CGparameter fp_DeferredMod_Specular;
3698 CGparameter fp_DistortScaleRefractReflect;
3699 CGparameter fp_EyePosition;
3700 CGparameter fp_FogColor;
3701 CGparameter fp_FogHeightFade;
3702 CGparameter fp_FogPlane;
3703 CGparameter fp_FogPlaneViewDist;
3704 CGparameter fp_FogRangeRecip;
3705 CGparameter fp_LightColor;
3706 CGparameter fp_LightDir;
3707 CGparameter fp_LightPosition;
3708 CGparameter fp_OffsetMapping_Scale;
3709 CGparameter fp_PixelSize;
3710 CGparameter fp_ReflectColor;
3711 CGparameter fp_ReflectFactor;
3712 CGparameter fp_ReflectOffset;
3713 CGparameter fp_RefractColor;
3714 CGparameter fp_Saturation;
3715 CGparameter fp_ScreenCenterRefractReflect;
3716 CGparameter fp_ScreenScaleRefractReflect;
3717 CGparameter fp_ScreenToDepth;
3718 CGparameter fp_ShadowMap_Parameters;
3719 CGparameter fp_ShadowMap_TextureScale;
3720 CGparameter fp_SpecularPower;
3721 CGparameter fp_UserVec1;
3722 CGparameter fp_UserVec2;
3723 CGparameter fp_UserVec3;
3724 CGparameter fp_UserVec4;
3725 CGparameter fp_ViewTintColor;
3726 CGparameter fp_ViewToLight;
3730 /// information about each possible shader permutation
3731 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3732 /// currently selected permutation
3733 r_cg_permutation_t *r_cg_permutation;
3734 /// storage for permutations linked in the hash table
3735 memexpandablearray_t r_cg_permutationarray;
3737 #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));}}
3739 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3741 //unsigned int hashdepth = 0;
3742 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3743 r_cg_permutation_t *p;
3744 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3746 if (p->mode == mode && p->permutation == permutation)
3748 //if (hashdepth > 10)
3749 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3754 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3756 p->permutation = permutation;
3757 p->hashnext = r_cg_permutationhash[mode][hashindex];
3758 r_cg_permutationhash[mode][hashindex] = p;
3759 //if (hashdepth > 10)
3760 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3764 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3767 if (!filename || !filename[0])
3769 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3772 if (printfromdisknotice)
3773 Con_DPrintf("from disk %s... ", filename);
3774 return shaderstring;
3776 else if (!strcmp(filename, "cg/default.cg"))
3778 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3779 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3781 return shaderstring;
3784 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3787 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3788 int vertstrings_count = 0, vertstring_length = 0;
3789 int geomstrings_count = 0, geomstring_length = 0;
3790 int fragstrings_count = 0, fragstring_length = 0;
3792 char *vertexstring, *geometrystring, *fragmentstring;
3793 char *vertstring, *geomstring, *fragstring;
3794 const char *vertstrings_list[32+3];
3795 const char *geomstrings_list[32+3];
3796 const char *fragstrings_list[32+3];
3797 char permutationname[256];
3798 CGprofile vertexProfile;
3799 CGprofile fragmentProfile;
3807 permutationname[0] = 0;
3808 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
3809 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3810 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3812 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3814 // the first pretext is which type of shader to compile as
3815 // (later these will all be bound together as a program object)
3816 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3817 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3818 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3820 // the second pretext is the mode (for example a light source)
3821 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3822 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3823 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3824 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3826 // now add all the permutation pretexts
3827 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3829 if (permutation & (1<<i))
3831 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3832 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3833 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3834 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3838 // keep line numbers correct
3839 vertstrings_list[vertstrings_count++] = "\n";
3840 geomstrings_list[geomstrings_count++] = "\n";
3841 fragstrings_list[fragstrings_count++] = "\n";
3845 // now append the shader text itself
3846 vertstrings_list[vertstrings_count++] = vertexstring;
3847 geomstrings_list[geomstrings_count++] = geometrystring;
3848 fragstrings_list[fragstrings_count++] = fragmentstring;
3850 // if any sources were NULL, clear the respective list
3852 vertstrings_count = 0;
3853 if (!geometrystring)
3854 geomstrings_count = 0;
3855 if (!fragmentstring)
3856 fragstrings_count = 0;
3858 vertstring_length = 0;
3859 for (i = 0;i < vertstrings_count;i++)
3860 vertstring_length += strlen(vertstrings_list[i]);
3861 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3862 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3863 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3865 geomstring_length = 0;
3866 for (i = 0;i < geomstrings_count;i++)
3867 geomstring_length += strlen(geomstrings_list[i]);
3868 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3869 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3870 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3872 fragstring_length = 0;
3873 for (i = 0;i < fragstrings_count;i++)
3874 fragstring_length += strlen(fragstrings_list[i]);
3875 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3876 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3877 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3881 //vertexProfile = CG_PROFILE_ARBVP1;
3882 //fragmentProfile = CG_PROFILE_ARBFP1;
3883 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3884 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3885 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3886 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3887 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3890 // compile the vertex program
3891 if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL)))
3894 cgCompileProgram(p->vprogram);CHECKCGERROR
3895 if (!cgIsProgramCompiled(p->vprogram))
3898 cgDestroyProgram(p->vprogram);CHECKCGERROR
3903 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3904 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3905 // look up all the uniform variable names we care about, so we don't
3906 // have to look them up every time we set them
3908 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
3909 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
3910 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
3911 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
3912 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
3913 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
3914 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3915 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3916 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3921 // compile the fragment program
3922 if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL)))
3924 cgCompileProgram(p->fprogram);CHECKCGERROR
3925 if (!cgIsProgramCompiled(p->fprogram))
3928 cgDestroyProgram(p->fprogram);CHECKCGERROR
3933 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3934 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3936 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
3937 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
3938 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3939 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3940 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
3941 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3942 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3943 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3944 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3945 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3946 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3947 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3948 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3949 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3950 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3951 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3952 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3953 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3954 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3955 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3956 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3957 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3958 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3959 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3960 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3961 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3962 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3963 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3964 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
3965 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3966 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
3967 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
3968 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
3969 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
3970 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
3971 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
3972 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
3973 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
3974 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
3975 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
3976 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
3977 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
3978 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
3979 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
3980 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
3981 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
3982 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
3983 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
3984 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
3985 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
3986 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
3987 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
3988 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
3989 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
3990 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
3991 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
3992 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
3993 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
3994 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
3995 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
3996 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
3997 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
3998 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
3999 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4000 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4001 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4002 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4003 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4004 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4005 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4006 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4011 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4012 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4014 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4018 Mem_Free(vertstring);
4020 Mem_Free(geomstring);
4022 Mem_Free(fragstring);
4024 Mem_Free(vertexstring);
4026 Mem_Free(geometrystring);
4028 Mem_Free(fragmentstring);
4031 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4033 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4036 if (r_cg_permutation != perm)
4038 r_cg_permutation = perm;
4039 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4041 if (!r_cg_permutation->compiled)
4042 R_CG_CompilePermutation(perm, mode, permutation);
4043 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4045 // remove features until we find a valid permutation
4047 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4049 // reduce i more quickly whenever it would not remove any bits
4050 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4051 if (!(permutation & j))
4054 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4055 if (!r_cg_permutation->compiled)
4056 R_CG_CompilePermutation(perm, mode, permutation);
4057 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4060 if (i >= SHADERPERMUTATION_COUNT)
4062 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4063 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4064 return; // no bit left to clear, entire mode is broken
4070 if (r_cg_permutation->vprogram)
4072 //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4073 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4074 //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4078 //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4079 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4081 if (r_cg_permutation->fprogram)
4083 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4084 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4085 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4089 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4090 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4094 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4097 void CG_BindTexture(CGparameter param, int texnum)
4099 cgGLSetTextureParameter(param, texnum);
4100 cgGLEnableTextureParameter(param);
4104 void R_GLSL_Restart_f(void)
4106 unsigned int i, limit;
4107 switch(vid.renderpath)
4109 case RENDERPATH_GL20:
4111 r_glsl_permutation_t *p;
4112 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4113 for (i = 0;i < limit;i++)
4115 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4117 GL_Backend_FreeProgram(p->program);
4118 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4121 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4124 case RENDERPATH_CGGL:
4127 r_cg_permutation_t *p;
4128 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4129 for (i = 0;i < limit;i++)
4131 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4134 cgDestroyProgram(p->vprogram);
4136 cgDestroyProgram(p->fprogram);
4137 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4141 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4144 case RENDERPATH_GL13:
4145 case RENDERPATH_GL11:
4150 void R_GLSL_DumpShader_f(void)
4155 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4158 FS_Print(file, "/* The engine may define the following macros:\n");
4159 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4160 for (i = 0;i < SHADERMODE_COUNT;i++)
4161 FS_Print(file, glslshadermodeinfo[i].pretext);
4162 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4163 FS_Print(file, shaderpermutationinfo[i].pretext);
4164 FS_Print(file, "*/\n");
4165 FS_Print(file, builtinshaderstring);
4167 Con_Printf("glsl/default.glsl written\n");
4170 Con_Printf("failed to write to glsl/default.glsl\n");
4173 file = FS_OpenRealFile("cg/default.cg", "w", false);
4176 FS_Print(file, "/* The engine may define the following macros:\n");
4177 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4178 for (i = 0;i < SHADERMODE_COUNT;i++)
4179 FS_Print(file, cgshadermodeinfo[i].pretext);
4180 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4181 FS_Print(file, shaderpermutationinfo[i].pretext);
4182 FS_Print(file, "*/\n");
4183 FS_Print(file, builtincgshaderstring);
4185 Con_Printf("cg/default.cg written\n");
4188 Con_Printf("failed to write to cg/default.cg\n");
4192 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4195 texturemode = GL_MODULATE;
4196 switch (vid.renderpath)
4198 case RENDERPATH_GL20:
4199 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))));
4200 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(first ));
4201 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, R_GetTexture(second));
4203 case RENDERPATH_CGGL:
4206 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))));
4207 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , R_GetTexture(first ));CHECKCGERROR
4208 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, R_GetTexture(second));CHECKCGERROR
4211 case RENDERPATH_GL13:
4212 R_Mesh_TexBind(0, R_GetTexture(first ));
4213 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4214 R_Mesh_TexBind(1, R_GetTexture(second));
4216 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4218 case RENDERPATH_GL11:
4219 R_Mesh_TexBind(0, R_GetTexture(first ));
4224 void R_SetupShader_DepthOrShadow(void)
4226 switch (vid.renderpath)
4228 case RENDERPATH_GL20:
4229 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4231 case RENDERPATH_CGGL:
4233 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4236 case RENDERPATH_GL13:
4237 R_Mesh_TexBind(0, 0);
4238 R_Mesh_TexBind(1, 0);
4240 case RENDERPATH_GL11:
4241 R_Mesh_TexBind(0, 0);
4246 void R_SetupShader_ShowDepth(void)
4248 switch (vid.renderpath)
4250 case RENDERPATH_GL20:
4251 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4253 case RENDERPATH_CGGL:
4255 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4258 case RENDERPATH_GL13:
4260 case RENDERPATH_GL11:
4265 extern qboolean r_shadow_usingdeferredprepass;
4266 extern cvar_t r_shadow_deferred_8bitrange;
4267 extern rtexture_t *r_shadow_attenuationgradienttexture;
4268 extern rtexture_t *r_shadow_attenuation2dtexture;
4269 extern rtexture_t *r_shadow_attenuation3dtexture;
4270 extern qboolean r_shadow_usingshadowmaprect;
4271 extern qboolean r_shadow_usingshadowmapcube;
4272 extern qboolean r_shadow_usingshadowmap2d;
4273 extern float r_shadow_shadowmap_texturescale[2];
4274 extern float r_shadow_shadowmap_parameters[4];
4275 extern qboolean r_shadow_shadowmapvsdct;
4276 extern qboolean r_shadow_shadowmapsampler;
4277 extern int r_shadow_shadowmappcf;
4278 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4279 extern rtexture_t *r_shadow_shadowmap2dtexture;
4280 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4281 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4282 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4283 extern int r_shadow_prepass_width;
4284 extern int r_shadow_prepass_height;
4285 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4286 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4287 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4288 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4289 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4291 // select a permutation of the lighting shader appropriate to this
4292 // combination of texture, entity, light source, and fogging, only use the
4293 // minimum features necessary to avoid wasting rendering time in the
4294 // fragment shader on features that are not being used
4295 unsigned int permutation = 0;
4296 unsigned int mode = 0;
4298 // TODO: implement geometry-shader based shadow volumes someday
4299 if (r_glsl_offsetmapping.integer)
4301 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4302 if (r_glsl_offsetmapping_reliefmapping.integer)
4303 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4305 if (rsurfacepass == RSURFPASS_BACKGROUND)
4307 // distorted background
4308 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4309 mode = SHADERMODE_WATER;
4311 mode = SHADERMODE_REFRACTION;
4313 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4315 // normalmap (deferred prepass), may use alpha test on diffuse
4316 mode = SHADERMODE_DEFERREDGEOMETRY;
4317 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4318 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4319 if (r_glsl_offsetmapping.integer)
4321 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4322 if (r_glsl_offsetmapping_reliefmapping.integer)
4323 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4326 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4329 mode = SHADERMODE_LIGHTSOURCE;
4330 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4331 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4332 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4333 permutation |= SHADERPERMUTATION_CUBEFILTER;
4334 if (diffusescale > 0)
4335 permutation |= SHADERPERMUTATION_DIFFUSE;
4336 if (specularscale > 0)
4337 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4338 if (r_refdef.fogenabled)
4339 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4340 if (rsurface.texture->colormapping)
4341 permutation |= SHADERPERMUTATION_COLORMAPPING;
4342 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4344 if (r_shadow_usingshadowmaprect)
4345 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4346 if (r_shadow_usingshadowmap2d)
4347 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4348 if (r_shadow_usingshadowmapcube)
4349 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4350 else if(r_shadow_shadowmapvsdct)
4351 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4353 if (r_shadow_shadowmapsampler)
4354 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4355 if (r_shadow_shadowmappcf > 1)
4356 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4357 else if (r_shadow_shadowmappcf)
4358 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4361 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4363 // unshaded geometry (fullbright or ambient model lighting)
4364 mode = SHADERMODE_FLATCOLOR;
4365 ambientscale = diffusescale = specularscale = 0;
4366 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4367 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4368 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4369 permutation |= SHADERPERMUTATION_GLOW;
4370 if (r_refdef.fogenabled)
4371 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4372 if (rsurface.texture->colormapping)
4373 permutation |= SHADERPERMUTATION_COLORMAPPING;
4374 if (r_glsl_offsetmapping.integer)
4376 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4377 if (r_glsl_offsetmapping_reliefmapping.integer)
4378 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4380 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4381 permutation |= SHADERPERMUTATION_REFLECTION;
4383 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4385 // directional model lighting
4386 mode = SHADERMODE_LIGHTDIRECTION;
4387 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4388 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4389 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4390 permutation |= SHADERPERMUTATION_GLOW;
4391 permutation |= SHADERPERMUTATION_DIFFUSE;
4392 if (specularscale > 0)
4393 permutation |= SHADERPERMUTATION_SPECULAR;
4394 if (r_refdef.fogenabled)
4395 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4396 if (rsurface.texture->colormapping)
4397 permutation |= SHADERPERMUTATION_COLORMAPPING;
4398 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4399 permutation |= SHADERPERMUTATION_REFLECTION;
4400 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4401 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4403 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4405 // ambient model lighting
4406 mode = SHADERMODE_LIGHTDIRECTION;
4407 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4408 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4409 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4410 permutation |= SHADERPERMUTATION_GLOW;
4411 if (r_refdef.fogenabled)
4412 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4413 if (rsurface.texture->colormapping)
4414 permutation |= SHADERPERMUTATION_COLORMAPPING;
4415 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4416 permutation |= SHADERPERMUTATION_REFLECTION;
4417 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4418 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4423 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4425 // deluxemapping (light direction texture)
4426 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4427 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4429 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4430 permutation |= SHADERPERMUTATION_DIFFUSE;
4431 if (specularscale > 0)
4432 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4434 else if (r_glsl_deluxemapping.integer >= 2)
4436 // fake deluxemapping (uniform light direction in tangentspace)
4437 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4438 permutation |= SHADERPERMUTATION_DIFFUSE;
4439 if (specularscale > 0)
4440 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4442 else if (rsurface.uselightmaptexture)
4444 // ordinary lightmapping (q1bsp, q3bsp)
4445 mode = SHADERMODE_LIGHTMAP;
4449 // ordinary vertex coloring (q3bsp)
4450 mode = SHADERMODE_VERTEXCOLOR;
4452 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4453 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4454 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4455 permutation |= SHADERPERMUTATION_GLOW;
4456 if (r_refdef.fogenabled)
4457 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4458 if (rsurface.texture->colormapping)
4459 permutation |= SHADERPERMUTATION_COLORMAPPING;
4460 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4461 permutation |= SHADERPERMUTATION_REFLECTION;
4462 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4463 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4465 if(permutation & SHADERPERMUTATION_SPECULAR)
4466 if(r_shadow_glossexact.integer)
4467 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4468 if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
4469 permutation |= SHADERPERMUTATION_ALPHAKILL;
4470 switch(vid.renderpath)
4472 case RENDERPATH_GL20:
4473 R_SetupShader_SetPermutationGLSL(mode, permutation);
4474 if (mode == SHADERMODE_LIGHTSOURCE)
4476 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4477 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4478 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4479 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);
4480 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);
4481 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
4483 // additive passes are only darkened by fog, not tinted
4484 if (r_glsl_permutation->loc_FogColor >= 0)
4485 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4486 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]);
4487 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]);
4488 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4492 if (mode == SHADERMODE_FLATCOLOR)
4494 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4496 else if (mode == SHADERMODE_LIGHTDIRECTION)
4498 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]);
4499 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
4500 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);
4501 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);
4502 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);
4503 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]);
4504 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]);
4508 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]);
4509 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]);
4510 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);
4511 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);
4512 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);
4514 // additive passes are only darkened by fog, not tinted
4515 if (r_glsl_permutation->loc_FogColor >= 0)
4517 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4518 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4520 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4522 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);
4523 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]);
4524 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]);
4525 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4526 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4527 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4528 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4529 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4531 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4532 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4533 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4534 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4535 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4536 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4537 if (r_glsl_permutation->loc_Color_Pants >= 0)
4539 if (rsurface.texture->pantstexture)
4540 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4542 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4544 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4546 if (rsurface.texture->shirttexture)
4547 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4549 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4551 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]);
4552 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4553 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4554 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4555 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4556 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]);
4558 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(r_texture_white ));
4559 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , R_GetTexture(r_texture_white ));
4560 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , R_GetTexture(r_texture_gammaramps ));
4561 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , R_GetTexture(rsurface.texture->nmaptexture ));
4562 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , R_GetTexture(rsurface.texture->basetexture ));
4563 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , R_GetTexture(rsurface.texture->glosstexture ));
4564 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , R_GetTexture(rsurface.texture->glowtexture ));
4565 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , R_GetTexture(rsurface.texture->backgroundnmaptexture ));
4566 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , R_GetTexture(rsurface.texture->backgroundbasetexture ));
4567 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , R_GetTexture(rsurface.texture->backgroundglosstexture ));
4568 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , R_GetTexture(rsurface.texture->backgroundglowtexture ));
4569 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , R_GetTexture(rsurface.texture->pantstexture ));
4570 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , R_GetTexture(rsurface.texture->shirttexture ));
4571 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , R_GetTexture(r_texture_fogattenuation ));
4572 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(r_texture_white ));
4573 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(r_texture_blanknormalmap ));
4574 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , R_GetTexture(r_shadow_attenuationgradienttexture ));
4575 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , R_GetTexture(r_texture_white ));
4576 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , R_GetTexture(r_texture_white ));
4577 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture ));
4578 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture ));
4579 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture ));
4580 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture ));
4581 if (rsurface.rtlight)
4583 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBindAll(GL20TU_CUBE , 0, 0, R_GetTexture(rsurface.rtlight->currentcubemap ), 0);
4584 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture ));
4585 if (r_shadow_usingshadowmapcube)
4586 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE , 0, 0, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
4587 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , R_GetTexture(r_shadow_shadowmap2dtexture ));
4588 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0, R_GetTexture(r_shadow_shadowmapvsdcttexture ), 0);
4592 case RENDERPATH_CGGL:
4594 R_SetupShader_SetPermutationCG(mode, permutation);
4595 if (mode == SHADERMODE_LIGHTSOURCE)
4597 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4598 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4602 if (mode == SHADERMODE_LIGHTDIRECTION)
4604 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
4607 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
4608 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4609 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4610 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4611 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
4614 if (mode == SHADERMODE_LIGHTSOURCE)
4616 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4617 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4618 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
4619 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
4620 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, specularscale, specularscale, specularscale);CHECKCGERROR
4622 // additive passes are only darkened by fog, not tinted
4623 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4624 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
4625 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
4626 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4630 if (mode == SHADERMODE_FLATCOLOR)
4632 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4634 else if (mode == SHADERMODE_LIGHTDIRECTION)
4636 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
4637 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);CHECKCGERROR
4638 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
4639 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
4640 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
4641 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
4642 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
4646 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
4647 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
4648 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
4649 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
4650 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
4652 // additive passes are only darkened by fog, not tinted
4653 if (r_cg_permutation->fp_FogColor)
4655 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4656 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4658 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4661 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
4662 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
4663 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
4664 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4665 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4666 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4667 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4668 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4670 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4671 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4672 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4673 if (r_cg_permutation->fp_Color_Pants)
4675 if (rsurface.texture->pantstexture)
4676 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4678 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4681 if (r_cg_permutation->fp_Color_Shirt)
4683 if (rsurface.texture->shirttexture)
4684 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4686 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4689 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
4690 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4691 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4692 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4693 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4694 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
4696 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , R_GetTexture(r_texture_white ));CHECKCGERROR
4697 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , R_GetTexture(r_texture_white ));CHECKCGERROR
4698 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , R_GetTexture(r_texture_gammaramps ));CHECKCGERROR
4699 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , R_GetTexture(rsurface.texture->nmaptexture ));CHECKCGERROR
4700 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , R_GetTexture(rsurface.texture->basetexture ));CHECKCGERROR
4701 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , R_GetTexture(rsurface.texture->glosstexture ));CHECKCGERROR
4702 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , R_GetTexture(rsurface.texture->glowtexture ));CHECKCGERROR
4703 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, R_GetTexture(rsurface.texture->backgroundnmaptexture ));CHECKCGERROR
4704 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , R_GetTexture(rsurface.texture->backgroundbasetexture ));CHECKCGERROR
4705 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , R_GetTexture(rsurface.texture->backgroundglosstexture ));CHECKCGERROR
4706 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , R_GetTexture(rsurface.texture->backgroundglowtexture ));CHECKCGERROR
4707 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , R_GetTexture(rsurface.texture->pantstexture ));CHECKCGERROR
4708 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , R_GetTexture(rsurface.texture->shirttexture ));CHECKCGERROR
4709 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , R_GetTexture(r_texture_fogattenuation ));CHECKCGERROR
4710 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , R_GetTexture(r_texture_white ));CHECKCGERROR
4711 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , R_GetTexture(r_texture_blanknormalmap ));CHECKCGERROR
4712 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , R_GetTexture(r_shadow_attenuationgradienttexture ));CHECKCGERROR
4713 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , R_GetTexture(r_texture_white ));CHECKCGERROR
4714 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , R_GetTexture(r_texture_white ));CHECKCGERROR
4715 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , R_GetTexture(r_shadow_prepassgeometrydepthtexture ));CHECKCGERROR
4716 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture ));CHECKCGERROR
4717 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , R_GetTexture(r_shadow_prepasslightingdiffusetexture ));CHECKCGERROR
4718 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , R_GetTexture(r_shadow_prepasslightingspeculartexture ));CHECKCGERROR
4719 if (rsurface.rtlight)
4721 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , R_GetTexture(rsurface.rtlight->currentcubemap ));CHECKCGERROR
4722 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , R_GetTexture(r_shadow_shadowmaprectangletexture ));CHECKCGERROR
4723 if (r_shadow_usingshadowmapcube)
4724 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));CHECKCGERROR
4725 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , R_GetTexture(r_shadow_shadowmap2dtexture ));CHECKCGERROR
4726 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture ));CHECKCGERROR
4732 case RENDERPATH_GL13:
4733 case RENDERPATH_GL11:
4738 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4740 // select a permutation of the lighting shader appropriate to this
4741 // combination of texture, entity, light source, and fogging, only use the
4742 // minimum features necessary to avoid wasting rendering time in the
4743 // fragment shader on features that are not being used
4744 unsigned int permutation = 0;
4745 unsigned int mode = 0;
4746 const float *lightcolorbase = rtlight->currentcolor;
4747 float ambientscale = rtlight->ambientscale;
4748 float diffusescale = rtlight->diffusescale;
4749 float specularscale = rtlight->specularscale;
4750 // this is the location of the light in view space
4751 vec3_t viewlightorigin;
4752 // this transforms from view space (camera) to light space (cubemap)
4753 matrix4x4_t viewtolight;
4754 matrix4x4_t lighttoview;
4755 float viewtolight16f[16];
4756 float range = 1.0f / r_shadow_deferred_8bitrange.value;
4758 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4759 if (rtlight->currentcubemap != r_texture_whitecube)
4760 permutation |= SHADERPERMUTATION_CUBEFILTER;
4761 if (diffusescale > 0)
4762 permutation |= SHADERPERMUTATION_DIFFUSE;
4763 if (specularscale > 0)
4765 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4766 if (r_shadow_glossexact.integer)
4767 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4769 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4771 if (r_shadow_usingshadowmaprect)
4772 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4773 if (r_shadow_usingshadowmap2d)
4774 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4775 if (r_shadow_usingshadowmapcube)
4776 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4777 else if(r_shadow_shadowmapvsdct)
4778 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4780 if (r_shadow_shadowmapsampler)
4781 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4782 if (r_shadow_shadowmappcf > 1)
4783 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4784 else if (r_shadow_shadowmappcf)
4785 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4787 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4788 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4789 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4790 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4791 switch(vid.renderpath)
4793 case RENDERPATH_GL20:
4794 R_SetupShader_SetPermutationGLSL(mode, permutation);
4795 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix , 1, false, gl_modelview16f);
4796 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4797 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
4798 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);
4799 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);
4800 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);
4801 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]);
4802 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]);
4803 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));
4804 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]);
4806 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , R_GetTexture(r_shadow_attenuationgradienttexture ));
4807 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture ));
4808 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture ));
4809 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBindAll(GL20TU_CUBE , 0, 0, R_GetTexture(rsurface.rtlight->currentcubemap ), 0);
4810 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture ));
4811 if (r_shadow_usingshadowmapcube)
4812 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE , 0, 0, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
4813 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , R_GetTexture(r_shadow_shadowmap2dtexture ));
4814 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0, R_GetTexture(r_shadow_shadowmapvsdcttexture ), 0);
4816 case RENDERPATH_CGGL:
4818 R_SetupShader_SetPermutationCG(mode, permutation);
4819 if (r_cg_permutation->vp_ModelViewMatrix ) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
4820 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4821 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4822 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
4823 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
4824 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
4825 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
4826 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
4827 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
4828 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
4830 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , R_GetTexture(r_shadow_attenuationgradienttexture ));CHECKCGERROR
4831 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , R_GetTexture(r_shadow_prepassgeometrydepthtexture ));CHECKCGERROR
4832 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture ));CHECKCGERROR
4833 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , R_GetTexture(rsurface.rtlight->currentcubemap ));CHECKCGERROR
4834 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , R_GetTexture(r_shadow_shadowmaprectangletexture ));CHECKCGERROR
4835 if (r_shadow_usingshadowmapcube)
4836 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));CHECKCGERROR
4837 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , R_GetTexture(r_shadow_shadowmap2dtexture ));CHECKCGERROR
4838 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture ));CHECKCGERROR
4841 case RENDERPATH_GL13:
4842 case RENDERPATH_GL11:
4847 #define SKINFRAME_HASH 1024
4851 int loadsequence; // incremented each level change
4852 memexpandablearray_t array;
4853 skinframe_t *hash[SKINFRAME_HASH];
4856 r_skinframe_t r_skinframe;
4858 void R_SkinFrame_PrepareForPurge(void)
4860 r_skinframe.loadsequence++;
4861 // wrap it without hitting zero
4862 if (r_skinframe.loadsequence >= 200)
4863 r_skinframe.loadsequence = 1;
4866 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
4870 // mark the skinframe as used for the purging code
4871 skinframe->loadsequence = r_skinframe.loadsequence;
4874 void R_SkinFrame_Purge(void)
4878 for (i = 0;i < SKINFRAME_HASH;i++)
4880 for (s = r_skinframe.hash[i];s;s = s->next)
4882 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
4884 if (s->merged == s->base)
4886 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
4887 R_PurgeTexture(s->stain );s->stain = NULL;
4888 R_PurgeTexture(s->merged);s->merged = NULL;
4889 R_PurgeTexture(s->base );s->base = NULL;
4890 R_PurgeTexture(s->pants );s->pants = NULL;
4891 R_PurgeTexture(s->shirt );s->shirt = NULL;
4892 R_PurgeTexture(s->nmap );s->nmap = NULL;
4893 R_PurgeTexture(s->gloss );s->gloss = NULL;
4894 R_PurgeTexture(s->glow );s->glow = NULL;
4895 R_PurgeTexture(s->fog );s->fog = NULL;
4896 s->loadsequence = 0;
4902 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
4904 char basename[MAX_QPATH];
4906 Image_StripImageExtension(name, basename, sizeof(basename));
4908 if( last == NULL ) {
4910 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4911 item = r_skinframe.hash[hashindex];
4916 // linearly search through the hash bucket
4917 for( ; item ; item = item->next ) {
4918 if( !strcmp( item->basename, basename ) ) {
4925 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
4929 char basename[MAX_QPATH];
4931 Image_StripImageExtension(name, basename, sizeof(basename));
4933 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4934 for (item = r_skinframe.hash[hashindex];item;item = item->next)
4935 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
4939 rtexture_t *dyntexture;
4940 // check whether its a dynamic texture
4941 dyntexture = CL_GetDynTexture( basename );
4942 if (!add && !dyntexture)
4944 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
4945 memset(item, 0, sizeof(*item));
4946 strlcpy(item->basename, basename, sizeof(item->basename));
4947 item->base = dyntexture; // either NULL or dyntexture handle
4948 item->textureflags = textureflags;
4949 item->comparewidth = comparewidth;
4950 item->compareheight = compareheight;
4951 item->comparecrc = comparecrc;
4952 item->next = r_skinframe.hash[hashindex];
4953 r_skinframe.hash[hashindex] = item;
4955 else if( item->base == NULL )
4957 rtexture_t *dyntexture;
4958 // check whether its a dynamic texture
4959 // 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]
4960 dyntexture = CL_GetDynTexture( basename );
4961 item->base = dyntexture; // either NULL or dyntexture handle
4964 R_SkinFrame_MarkUsed(item);
4968 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
4970 unsigned long long avgcolor[5], wsum; \
4978 for(pix = 0; pix < cnt; ++pix) \
4981 for(comp = 0; comp < 3; ++comp) \
4983 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
4986 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4988 for(comp = 0; comp < 3; ++comp) \
4989 avgcolor[comp] += getpixel * w; \
4992 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4993 avgcolor[4] += getpixel; \
4995 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
4997 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
4998 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
4999 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5000 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5003 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5006 unsigned char *pixels;
5007 unsigned char *bumppixels;
5008 unsigned char *basepixels = NULL;
5009 int basepixels_width;
5010 int basepixels_height;
5011 skinframe_t *skinframe;
5013 if (cls.state == ca_dedicated)
5016 // return an existing skinframe if already loaded
5017 // if loading of the first image fails, don't make a new skinframe as it
5018 // would cause all future lookups of this to be missing
5019 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5020 if (skinframe && skinframe->base)
5023 basepixels = loadimagepixelsbgra(name, complain, true);
5024 if (basepixels == NULL)
5027 if (developer_loading.integer)
5028 Con_Printf("loading skin \"%s\"\n", name);
5030 // we've got some pixels to store, so really allocate this new texture now
5032 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5033 skinframe->stain = NULL;
5034 skinframe->merged = NULL;
5035 skinframe->base = r_texture_notexture;
5036 skinframe->pants = NULL;
5037 skinframe->shirt = NULL;
5038 skinframe->nmap = r_texture_blanknormalmap;
5039 skinframe->gloss = NULL;
5040 skinframe->glow = NULL;
5041 skinframe->fog = NULL;
5042 skinframe->hasalpha = false;
5044 basepixels_width = image_width;
5045 basepixels_height = image_height;
5046 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);
5048 if (textureflags & TEXF_ALPHA)
5050 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5052 if (basepixels[j] < 255)
5054 skinframe->hasalpha = true;
5058 if (r_loadfog && skinframe->hasalpha)
5060 // has transparent pixels
5061 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5062 for (j = 0;j < image_width * image_height * 4;j += 4)
5067 pixels[j+3] = basepixels[j+3];
5069 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);
5074 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5075 //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]);
5077 // _norm is the name used by tenebrae and has been adopted as standard
5078 if (r_loadnormalmap)
5080 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5082 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);
5086 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5088 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5089 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5090 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);
5092 Mem_Free(bumppixels);
5094 else if (r_shadow_bumpscale_basetexture.value > 0)
5096 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5097 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5098 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);
5102 // _luma is supported for tenebrae compatibility
5103 // (I think it's a very stupid name, but oh well)
5104 // _glow is the preferred name
5105 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;}
5106 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;}
5107 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;}
5108 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;}
5111 Mem_Free(basepixels);
5116 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5117 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5120 unsigned char *temp1, *temp2;
5121 skinframe_t *skinframe;
5123 if (cls.state == ca_dedicated)
5126 // if already loaded just return it, otherwise make a new skinframe
5127 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5128 if (skinframe && skinframe->base)
5131 skinframe->stain = NULL;
5132 skinframe->merged = NULL;
5133 skinframe->base = r_texture_notexture;
5134 skinframe->pants = NULL;
5135 skinframe->shirt = NULL;
5136 skinframe->nmap = r_texture_blanknormalmap;
5137 skinframe->gloss = NULL;
5138 skinframe->glow = NULL;
5139 skinframe->fog = NULL;
5140 skinframe->hasalpha = false;
5142 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5146 if (developer_loading.integer)
5147 Con_Printf("loading 32bit skin \"%s\"\n", name);
5149 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5151 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5152 temp2 = temp1 + width * height * 4;
5153 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5154 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5157 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5158 if (textureflags & TEXF_ALPHA)
5160 for (i = 3;i < width * height * 4;i += 4)
5162 if (skindata[i] < 255)
5164 skinframe->hasalpha = true;
5168 if (r_loadfog && skinframe->hasalpha)
5170 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5171 memcpy(fogpixels, skindata, width * height * 4);
5172 for (i = 0;i < width * height * 4;i += 4)
5173 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5174 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5175 Mem_Free(fogpixels);
5179 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5180 //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]);
5185 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5189 skinframe_t *skinframe;
5191 if (cls.state == ca_dedicated)
5194 // if already loaded just return it, otherwise make a new skinframe
5195 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5196 if (skinframe && skinframe->base)
5199 skinframe->stain = NULL;
5200 skinframe->merged = NULL;
5201 skinframe->base = r_texture_notexture;
5202 skinframe->pants = NULL;
5203 skinframe->shirt = NULL;
5204 skinframe->nmap = r_texture_blanknormalmap;
5205 skinframe->gloss = NULL;
5206 skinframe->glow = NULL;
5207 skinframe->fog = NULL;
5208 skinframe->hasalpha = false;
5210 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5214 if (developer_loading.integer)
5215 Con_Printf("loading quake skin \"%s\"\n", name);
5217 // 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)
5218 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5219 memcpy(skinframe->qpixels, skindata, width*height);
5220 skinframe->qwidth = width;
5221 skinframe->qheight = height;
5224 for (i = 0;i < width * height;i++)
5225 featuresmask |= palette_featureflags[skindata[i]];
5227 skinframe->hasalpha = false;
5228 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5229 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5230 skinframe->qgeneratemerged = true;
5231 skinframe->qgeneratebase = skinframe->qhascolormapping;
5232 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5234 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5235 //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]);
5240 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5244 unsigned char *skindata;
5246 if (!skinframe->qpixels)
5249 if (!skinframe->qhascolormapping)
5250 colormapped = false;
5254 if (!skinframe->qgeneratebase)
5259 if (!skinframe->qgeneratemerged)
5263 width = skinframe->qwidth;
5264 height = skinframe->qheight;
5265 skindata = skinframe->qpixels;
5267 if (skinframe->qgeneratenmap)
5269 unsigned char *temp1, *temp2;
5270 skinframe->qgeneratenmap = false;
5271 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5272 temp2 = temp1 + width * height * 4;
5273 // use either a custom palette or the quake palette
5274 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5275 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5276 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5280 if (skinframe->qgenerateglow)
5282 skinframe->qgenerateglow = false;
5283 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5288 skinframe->qgeneratebase = false;
5289 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);
5290 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5291 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5295 skinframe->qgeneratemerged = false;
5296 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5299 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5301 Mem_Free(skinframe->qpixels);
5302 skinframe->qpixels = NULL;
5306 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)
5309 skinframe_t *skinframe;
5311 if (cls.state == ca_dedicated)
5314 // if already loaded just return it, otherwise make a new skinframe
5315 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5316 if (skinframe && skinframe->base)
5319 skinframe->stain = NULL;
5320 skinframe->merged = NULL;
5321 skinframe->base = r_texture_notexture;
5322 skinframe->pants = NULL;
5323 skinframe->shirt = NULL;
5324 skinframe->nmap = r_texture_blanknormalmap;
5325 skinframe->gloss = NULL;
5326 skinframe->glow = NULL;
5327 skinframe->fog = NULL;
5328 skinframe->hasalpha = false;
5330 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5334 if (developer_loading.integer)
5335 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5337 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5338 if (textureflags & TEXF_ALPHA)
5340 for (i = 0;i < width * height;i++)
5342 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5344 skinframe->hasalpha = true;
5348 if (r_loadfog && skinframe->hasalpha)
5349 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5352 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5353 //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]);
5358 skinframe_t *R_SkinFrame_LoadMissing(void)
5360 skinframe_t *skinframe;
5362 if (cls.state == ca_dedicated)
5365 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5366 skinframe->stain = NULL;
5367 skinframe->merged = NULL;
5368 skinframe->base = r_texture_notexture;
5369 skinframe->pants = NULL;
5370 skinframe->shirt = NULL;
5371 skinframe->nmap = r_texture_blanknormalmap;
5372 skinframe->gloss = NULL;
5373 skinframe->glow = NULL;
5374 skinframe->fog = NULL;
5375 skinframe->hasalpha = false;
5377 skinframe->avgcolor[0] = rand() / RAND_MAX;
5378 skinframe->avgcolor[1] = rand() / RAND_MAX;
5379 skinframe->avgcolor[2] = rand() / RAND_MAX;
5380 skinframe->avgcolor[3] = 1;
5385 void R_Main_FreeViewCache(void)
5387 if (r_refdef.viewcache.entityvisible)
5388 Mem_Free(r_refdef.viewcache.entityvisible);
5389 if (r_refdef.viewcache.world_pvsbits)
5390 Mem_Free(r_refdef.viewcache.world_pvsbits);
5391 if (r_refdef.viewcache.world_leafvisible)
5392 Mem_Free(r_refdef.viewcache.world_leafvisible);
5393 if (r_refdef.viewcache.world_surfacevisible)
5394 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5395 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5398 void R_Main_ResizeViewCache(void)
5400 int numentities = r_refdef.scene.numentities;
5401 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5402 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5403 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5404 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5405 if (r_refdef.viewcache.maxentities < numentities)
5407 r_refdef.viewcache.maxentities = numentities;
5408 if (r_refdef.viewcache.entityvisible)
5409 Mem_Free(r_refdef.viewcache.entityvisible);
5410 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5412 if (r_refdef.viewcache.world_numclusters != numclusters)
5414 r_refdef.viewcache.world_numclusters = numclusters;
5415 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5416 if (r_refdef.viewcache.world_pvsbits)
5417 Mem_Free(r_refdef.viewcache.world_pvsbits);
5418 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5420 if (r_refdef.viewcache.world_numleafs != numleafs)
5422 r_refdef.viewcache.world_numleafs = numleafs;
5423 if (r_refdef.viewcache.world_leafvisible)
5424 Mem_Free(r_refdef.viewcache.world_leafvisible);
5425 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5427 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5429 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5430 if (r_refdef.viewcache.world_surfacevisible)
5431 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5432 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5436 extern rtexture_t *loadingscreentexture;
5437 void gl_main_start(void)
5439 loadingscreentexture = NULL;
5440 r_texture_blanknormalmap = NULL;
5441 r_texture_white = NULL;
5442 r_texture_grey128 = NULL;
5443 r_texture_black = NULL;
5444 r_texture_whitecube = NULL;
5445 r_texture_normalizationcube = NULL;
5446 r_texture_fogattenuation = NULL;
5447 r_texture_gammaramps = NULL;
5449 switch(vid.renderpath)
5451 case RENDERPATH_GL20:
5452 case RENDERPATH_CGGL:
5453 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5454 Cvar_SetValueQuick(&gl_combine, 1);
5455 Cvar_SetValueQuick(&r_glsl, 1);
5456 r_loadnormalmap = true;
5460 case RENDERPATH_GL13:
5461 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5462 Cvar_SetValueQuick(&gl_combine, 1);
5463 Cvar_SetValueQuick(&r_glsl, 0);
5464 r_loadnormalmap = false;
5465 r_loadgloss = false;
5468 case RENDERPATH_GL11:
5469 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5470 Cvar_SetValueQuick(&gl_combine, 0);
5471 Cvar_SetValueQuick(&r_glsl, 0);
5472 r_loadnormalmap = false;
5473 r_loadgloss = false;
5479 R_FrameData_Reset();
5483 memset(r_queries, 0, sizeof(r_queries));
5485 r_qwskincache = NULL;
5486 r_qwskincache_size = 0;
5488 // set up r_skinframe loading system for textures
5489 memset(&r_skinframe, 0, sizeof(r_skinframe));
5490 r_skinframe.loadsequence = 1;
5491 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5493 r_main_texturepool = R_AllocTexturePool();
5494 R_BuildBlankTextures();
5496 if (vid.support.arb_texture_cube_map)
5499 R_BuildNormalizationCube();
5501 r_texture_fogattenuation = NULL;
5502 r_texture_gammaramps = NULL;
5503 //r_texture_fogintensity = NULL;
5504 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5505 memset(&r_waterstate, 0, sizeof(r_waterstate));
5506 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5507 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5509 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5510 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5512 memset(&r_svbsp, 0, sizeof (r_svbsp));
5514 r_refdef.fogmasktable_density = 0;
5517 void gl_main_shutdown(void)
5520 R_FrameData_Reset();
5522 R_Main_FreeViewCache();
5525 qglDeleteQueriesARB(r_maxqueries, r_queries);
5529 memset(r_queries, 0, sizeof(r_queries));
5531 r_qwskincache = NULL;
5532 r_qwskincache_size = 0;
5534 // clear out the r_skinframe state
5535 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5536 memset(&r_skinframe, 0, sizeof(r_skinframe));
5539 Mem_Free(r_svbsp.nodes);
5540 memset(&r_svbsp, 0, sizeof (r_svbsp));
5541 R_FreeTexturePool(&r_main_texturepool);
5542 loadingscreentexture = NULL;
5543 r_texture_blanknormalmap = NULL;
5544 r_texture_white = NULL;
5545 r_texture_grey128 = NULL;
5546 r_texture_black = NULL;
5547 r_texture_whitecube = NULL;
5548 r_texture_normalizationcube = NULL;
5549 r_texture_fogattenuation = NULL;
5550 r_texture_gammaramps = NULL;
5551 //r_texture_fogintensity = NULL;
5552 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5553 memset(&r_waterstate, 0, sizeof(r_waterstate));
5557 extern void CL_ParseEntityLump(char *entitystring);
5558 void gl_main_newmap(void)
5560 // FIXME: move this code to client
5562 char *entities, entname[MAX_QPATH];
5564 Mem_Free(r_qwskincache);
5565 r_qwskincache = NULL;
5566 r_qwskincache_size = 0;
5569 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5570 l = (int)strlen(entname) - 4;
5571 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5573 memcpy(entname + l, ".ent", 5);
5574 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5576 CL_ParseEntityLump(entities);
5581 if (cl.worldmodel->brush.entities)
5582 CL_ParseEntityLump(cl.worldmodel->brush.entities);
5584 R_Main_FreeViewCache();
5586 R_FrameData_Reset();
5589 void GL_Main_Init(void)
5591 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5593 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5594 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5595 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5596 if (gamemode == GAME_NEHAHRA)
5598 Cvar_RegisterVariable (&gl_fogenable);
5599 Cvar_RegisterVariable (&gl_fogdensity);
5600 Cvar_RegisterVariable (&gl_fogred);
5601 Cvar_RegisterVariable (&gl_foggreen);
5602 Cvar_RegisterVariable (&gl_fogblue);
5603 Cvar_RegisterVariable (&gl_fogstart);
5604 Cvar_RegisterVariable (&gl_fogend);
5605 Cvar_RegisterVariable (&gl_skyclip);
5607 Cvar_RegisterVariable(&r_motionblur);
5608 Cvar_RegisterVariable(&r_motionblur_maxblur);
5609 Cvar_RegisterVariable(&r_motionblur_bmin);
5610 Cvar_RegisterVariable(&r_motionblur_vmin);
5611 Cvar_RegisterVariable(&r_motionblur_vmax);
5612 Cvar_RegisterVariable(&r_motionblur_vcoeff);
5613 Cvar_RegisterVariable(&r_motionblur_randomize);
5614 Cvar_RegisterVariable(&r_damageblur);
5615 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5616 Cvar_RegisterVariable(&r_equalize_entities_minambient);
5617 Cvar_RegisterVariable(&r_equalize_entities_by);
5618 Cvar_RegisterVariable(&r_equalize_entities_to);
5619 Cvar_RegisterVariable(&r_depthfirst);
5620 Cvar_RegisterVariable(&r_useinfinitefarclip);
5621 Cvar_RegisterVariable(&r_farclip_base);
5622 Cvar_RegisterVariable(&r_farclip_world);
5623 Cvar_RegisterVariable(&r_nearclip);
5624 Cvar_RegisterVariable(&r_showbboxes);
5625 Cvar_RegisterVariable(&r_showsurfaces);
5626 Cvar_RegisterVariable(&r_showtris);
5627 Cvar_RegisterVariable(&r_shownormals);
5628 Cvar_RegisterVariable(&r_showlighting);
5629 Cvar_RegisterVariable(&r_showshadowvolumes);
5630 Cvar_RegisterVariable(&r_showcollisionbrushes);
5631 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5632 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5633 Cvar_RegisterVariable(&r_showdisabledepthtest);
5634 Cvar_RegisterVariable(&r_drawportals);
5635 Cvar_RegisterVariable(&r_drawentities);
5636 Cvar_RegisterVariable(&r_cullentities_trace);
5637 Cvar_RegisterVariable(&r_cullentities_trace_samples);
5638 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5639 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5640 Cvar_RegisterVariable(&r_cullentities_trace_delay);
5641 Cvar_RegisterVariable(&r_drawviewmodel);
5642 Cvar_RegisterVariable(&r_speeds);
5643 Cvar_RegisterVariable(&r_fullbrights);
5644 Cvar_RegisterVariable(&r_wateralpha);
5645 Cvar_RegisterVariable(&r_dynamic);
5646 Cvar_RegisterVariable(&r_fullbright);
5647 Cvar_RegisterVariable(&r_shadows);
5648 Cvar_RegisterVariable(&r_shadows_darken);
5649 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5650 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5651 Cvar_RegisterVariable(&r_shadows_throwdistance);
5652 Cvar_RegisterVariable(&r_shadows_throwdirection);
5653 Cvar_RegisterVariable(&r_q1bsp_skymasking);
5654 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5655 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5656 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5657 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5658 Cvar_RegisterVariable(&r_fog_exp2);
5659 Cvar_RegisterVariable(&r_drawfog);
5660 Cvar_RegisterVariable(&r_transparentdepthmasking);
5661 Cvar_RegisterVariable(&r_textureunits);
5662 Cvar_RegisterVariable(&gl_combine);
5663 Cvar_RegisterVariable(&r_glsl);
5664 Cvar_RegisterVariable(&r_glsl_deluxemapping);
5665 Cvar_RegisterVariable(&r_glsl_offsetmapping);
5666 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5667 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5668 Cvar_RegisterVariable(&r_glsl_postprocess);
5669 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5670 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5671 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5672 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5673 Cvar_RegisterVariable(&r_water);
5674 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5675 Cvar_RegisterVariable(&r_water_clippingplanebias);
5676 Cvar_RegisterVariable(&r_water_refractdistort);
5677 Cvar_RegisterVariable(&r_water_reflectdistort);
5678 Cvar_RegisterVariable(&r_lerpsprites);
5679 Cvar_RegisterVariable(&r_lerpmodels);
5680 Cvar_RegisterVariable(&r_lerplightstyles);
5681 Cvar_RegisterVariable(&r_waterscroll);
5682 Cvar_RegisterVariable(&r_bloom);
5683 Cvar_RegisterVariable(&r_bloom_colorscale);
5684 Cvar_RegisterVariable(&r_bloom_brighten);
5685 Cvar_RegisterVariable(&r_bloom_blur);
5686 Cvar_RegisterVariable(&r_bloom_resolution);
5687 Cvar_RegisterVariable(&r_bloom_colorexponent);
5688 Cvar_RegisterVariable(&r_bloom_colorsubtract);
5689 Cvar_RegisterVariable(&r_hdr);
5690 Cvar_RegisterVariable(&r_hdr_scenebrightness);
5691 Cvar_RegisterVariable(&r_hdr_glowintensity);
5692 Cvar_RegisterVariable(&r_hdr_range);
5693 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5694 Cvar_RegisterVariable(&developer_texturelogging);
5695 Cvar_RegisterVariable(&gl_lightmaps);
5696 Cvar_RegisterVariable(&r_test);
5697 Cvar_RegisterVariable(&r_batchmode);
5698 Cvar_RegisterVariable(&r_glsl_saturation);
5699 Cvar_RegisterVariable(&r_framedatasize);
5700 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5701 Cvar_SetValue("r_fullbrights", 0);
5702 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5704 Cvar_RegisterVariable(&r_track_sprites);
5705 Cvar_RegisterVariable(&r_track_sprites_flags);
5706 Cvar_RegisterVariable(&r_track_sprites_scalew);
5707 Cvar_RegisterVariable(&r_track_sprites_scaleh);
5710 extern void R_Textures_Init(void);
5711 extern void GL_Draw_Init(void);
5712 extern void GL_Main_Init(void);
5713 extern void R_Shadow_Init(void);
5714 extern void R_Sky_Init(void);
5715 extern void GL_Surf_Init(void);
5716 extern void R_Particles_Init(void);
5717 extern void R_Explosion_Init(void);
5718 extern void gl_backend_init(void);
5719 extern void Sbar_Init(void);
5720 extern void R_LightningBeams_Init(void);
5721 extern void Mod_RenderInit(void);
5722 extern void Font_Init(void);
5724 void Render_Init(void)
5737 R_LightningBeams_Init();
5746 extern char *ENGINE_EXTENSIONS;
5749 gl_renderer = (const char *)qglGetString(GL_RENDERER);
5750 gl_vendor = (const char *)qglGetString(GL_VENDOR);
5751 gl_version = (const char *)qglGetString(GL_VERSION);
5752 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5756 if (!gl_platformextensions)
5757 gl_platformextensions = "";
5759 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5760 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5761 Con_Printf("GL_VERSION: %s\n", gl_version);
5762 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
5763 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
5765 VID_CheckExtensions();
5767 // LordHavoc: report supported extensions
5768 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
5770 // clear to black (loading plaque will be seen over this)
5772 qglClearColor(0,0,0,1);CHECKGLERROR
5773 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
5776 int R_CullBox(const vec3_t mins, const vec3_t maxs)
5780 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5782 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
5785 p = r_refdef.view.frustum + i;
5790 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5794 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5798 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5802 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5806 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5810 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5814 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5818 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5826 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
5830 for (i = 0;i < numplanes;i++)
5837 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5841 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5845 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5849 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5853 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5857 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5861 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5865 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5873 //==================================================================================
5875 // LordHavoc: this stores temporary data used within the same frame
5877 qboolean r_framedata_failed;
5878 static size_t r_framedata_size;
5879 static size_t r_framedata_current;
5880 static void *r_framedata_base;
5882 void R_FrameData_Reset(void)
5884 if (r_framedata_base);
5885 Mem_Free(r_framedata_base);
5886 r_framedata_base = NULL;
5887 r_framedata_size = 0;
5888 r_framedata_current = 0;
5889 r_framedata_failed = false;
5892 void R_FrameData_NewFrame(void)
5895 if (r_framedata_failed)
5896 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
5897 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
5898 wantedsize = bound(65536, wantedsize, 128*1024*1024);
5899 if (r_framedata_size != wantedsize)
5901 r_framedata_size = wantedsize;
5902 if (r_framedata_base);
5903 Mem_Free(r_framedata_base);
5904 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
5906 r_framedata_current = 0;
5907 r_framedata_failed = false;
5910 void *R_FrameData_Alloc(size_t size)
5914 // align to 16 byte boundary
5915 size = (size + 15) & ~15;
5916 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
5917 r_framedata_current += size;
5920 if (r_framedata_current > r_framedata_size)
5921 r_framedata_failed = true;
5923 // return NULL on everything after a failure
5924 if (r_framedata_failed)
5930 void *R_FrameData_Store(size_t size, void *data)
5932 void *d = R_FrameData_Alloc(size);
5934 memcpy(d, data, size);
5938 //==================================================================================
5940 // LordHavoc: animcache originally written by Echon, rewritten since then
5943 * Animation cache prevents re-generating mesh data for an animated model
5944 * multiple times in one frame for lighting, shadowing, reflections, etc.
5947 void R_AnimCache_Free(void)
5951 void R_AnimCache_ClearCache(void)
5954 entity_render_t *ent;
5956 for (i = 0;i < r_refdef.scene.numentities;i++)
5958 ent = r_refdef.scene.entities[i];
5959 ent->animcache_vertex3f = NULL;
5960 ent->animcache_normal3f = NULL;
5961 ent->animcache_svector3f = NULL;
5962 ent->animcache_tvector3f = NULL;
5966 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5968 dp_model_t *model = ent->model;
5970 // see if it's already cached this frame
5971 if (ent->animcache_vertex3f)
5973 // add normals/tangents if needed
5974 if (wantnormals || wanttangents)
5976 if (ent->animcache_normal3f)
5977 wantnormals = false;
5978 if (ent->animcache_svector3f)
5979 wanttangents = false;
5980 if (wantnormals || wanttangents)
5982 numvertices = model->surfmesh.num_vertices;
5984 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
5987 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
5988 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
5990 if (!r_framedata_failed)
5991 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5997 // see if this ent is worth caching
5998 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6000 // get some memory for this entity and generate mesh data
6001 numvertices = model->surfmesh.num_vertices;
6002 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6004 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6007 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6008 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6010 if (!r_framedata_failed)
6011 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6013 return !r_framedata_failed;
6016 void R_AnimCache_CacheVisibleEntities(void)
6019 qboolean wantnormals = !r_showsurfaces.integer;
6020 qboolean wanttangents = !r_showsurfaces.integer;
6022 switch(vid.renderpath)
6024 case RENDERPATH_GL20:
6025 case RENDERPATH_CGGL:
6027 case RENDERPATH_GL13:
6028 case RENDERPATH_GL11:
6029 wanttangents = false;
6033 // TODO: thread this
6034 // NOTE: R_PrepareRTLights() also caches entities
6036 for (i = 0;i < r_refdef.scene.numentities;i++)
6037 if (r_refdef.viewcache.entityvisible[i])
6038 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6040 if (r_shadows.integer)
6041 for (i = 0;i < r_refdef.scene.numentities;i++)
6042 if (!r_refdef.viewcache.entityvisible[i])
6043 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6046 //==================================================================================
6048 static void R_View_UpdateEntityLighting (void)
6051 entity_render_t *ent;
6052 vec3_t tempdiffusenormal, avg;
6053 vec_t f, fa, fd, fdd;
6055 for (i = 0;i < r_refdef.scene.numentities;i++)
6057 ent = r_refdef.scene.entities[i];
6059 // skip unseen models
6060 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6064 if (ent->model && ent->model->brush.num_leafs)
6066 // TODO: use modellight for r_ambient settings on world?
6067 VectorSet(ent->modellight_ambient, 0, 0, 0);
6068 VectorSet(ent->modellight_diffuse, 0, 0, 0);
6069 VectorSet(ent->modellight_lightdir, 0, 0, 1);
6073 // fetch the lighting from the worldmodel data
6074 VectorClear(ent->modellight_ambient);
6075 VectorClear(ent->modellight_diffuse);
6076 VectorClear(tempdiffusenormal);
6077 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6080 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6081 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6082 if(ent->flags & RENDER_EQUALIZE)
6084 // first fix up ambient lighting...
6085 if(r_equalize_entities_minambient.value > 0)
6087 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6090 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6091 if(fa < r_equalize_entities_minambient.value * fd)
6094 // fa'/fd' = minambient
6095 // fa'+0.25*fd' = fa+0.25*fd
6097 // fa' = fd' * minambient
6098 // fd'*(0.25+minambient) = fa+0.25*fd
6100 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6101 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6103 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6104 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
6105 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6106 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6111 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6113 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6114 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6117 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6118 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6119 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6125 VectorSet(ent->modellight_ambient, 1, 1, 1);
6127 // move the light direction into modelspace coordinates for lighting code
6128 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6129 if(VectorLength2(ent->modellight_lightdir) == 0)
6130 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6131 VectorNormalize(ent->modellight_lightdir);
6135 #define MAX_LINEOFSIGHTTRACES 64
6137 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6140 vec3_t boxmins, boxmaxs;
6143 dp_model_t *model = r_refdef.scene.worldmodel;
6145 if (!model || !model->brush.TraceLineOfSight)
6148 // expand the box a little
6149 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6150 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6151 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6152 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6153 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6154 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6157 VectorCopy(eye, start);
6158 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6159 if (model->brush.TraceLineOfSight(model, start, end))
6162 // try various random positions
6163 for (i = 0;i < numsamples;i++)
6165 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6166 if (model->brush.TraceLineOfSight(model, start, end))
6174 static void R_View_UpdateEntityVisible (void)
6179 entity_render_t *ent;
6181 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6182 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6184 // worldmodel can check visibility
6185 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6186 for (i = 0;i < r_refdef.scene.numentities;i++)
6188 ent = r_refdef.scene.entities[i];
6189 if (!(ent->flags & renderimask))
6190 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)))
6191 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))
6192 r_refdef.viewcache.entityvisible[i] = true;
6194 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6196 for (i = 0;i < r_refdef.scene.numentities;i++)
6198 ent = r_refdef.scene.entities[i];
6199 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6201 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6203 continue; // temp entities do pvs only
6204 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6205 ent->last_trace_visibility = realtime;
6206 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6207 r_refdef.viewcache.entityvisible[i] = 0;
6214 // no worldmodel or it can't check visibility
6215 for (i = 0;i < r_refdef.scene.numentities;i++)
6217 ent = r_refdef.scene.entities[i];
6218 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));
6223 /// only used if skyrendermasked, and normally returns false
6224 int R_DrawBrushModelsSky (void)
6227 entity_render_t *ent;
6230 for (i = 0;i < r_refdef.scene.numentities;i++)
6232 if (!r_refdef.viewcache.entityvisible[i])
6234 ent = r_refdef.scene.entities[i];
6235 if (!ent->model || !ent->model->DrawSky)
6237 ent->model->DrawSky(ent);
6243 static void R_DrawNoModel(entity_render_t *ent);
6244 static void R_DrawModels(void)
6247 entity_render_t *ent;
6249 for (i = 0;i < r_refdef.scene.numentities;i++)
6251 if (!r_refdef.viewcache.entityvisible[i])
6253 ent = r_refdef.scene.entities[i];
6254 r_refdef.stats.entities++;
6255 if (ent->model && ent->model->Draw != NULL)
6256 ent->model->Draw(ent);
6262 static void R_DrawModelsDepth(void)
6265 entity_render_t *ent;
6267 for (i = 0;i < r_refdef.scene.numentities;i++)
6269 if (!r_refdef.viewcache.entityvisible[i])
6271 ent = r_refdef.scene.entities[i];
6272 if (ent->model && ent->model->DrawDepth != NULL)
6273 ent->model->DrawDepth(ent);
6277 static void R_DrawModelsDebug(void)
6280 entity_render_t *ent;
6282 for (i = 0;i < r_refdef.scene.numentities;i++)
6284 if (!r_refdef.viewcache.entityvisible[i])
6286 ent = r_refdef.scene.entities[i];
6287 if (ent->model && ent->model->DrawDebug != NULL)
6288 ent->model->DrawDebug(ent);
6292 static void R_DrawModelsAddWaterPlanes(void)
6295 entity_render_t *ent;
6297 for (i = 0;i < r_refdef.scene.numentities;i++)
6299 if (!r_refdef.viewcache.entityvisible[i])
6301 ent = r_refdef.scene.entities[i];
6302 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6303 ent->model->DrawAddWaterPlanes(ent);
6307 static void R_View_SetFrustum(void)
6310 double slopex, slopey;
6311 vec3_t forward, left, up, origin;
6313 // we can't trust r_refdef.view.forward and friends in reflected scenes
6314 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6317 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6318 r_refdef.view.frustum[0].normal[1] = 0 - 0;
6319 r_refdef.view.frustum[0].normal[2] = -1 - 0;
6320 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6321 r_refdef.view.frustum[1].normal[1] = 0 + 0;
6322 r_refdef.view.frustum[1].normal[2] = -1 + 0;
6323 r_refdef.view.frustum[2].normal[0] = 0 - 0;
6324 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6325 r_refdef.view.frustum[2].normal[2] = -1 - 0;
6326 r_refdef.view.frustum[3].normal[0] = 0 + 0;
6327 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6328 r_refdef.view.frustum[3].normal[2] = -1 + 0;
6332 zNear = r_refdef.nearclip;
6333 nudge = 1.0 - 1.0 / (1<<23);
6334 r_refdef.view.frustum[4].normal[0] = 0 - 0;
6335 r_refdef.view.frustum[4].normal[1] = 0 - 0;
6336 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6337 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6338 r_refdef.view.frustum[5].normal[0] = 0 + 0;
6339 r_refdef.view.frustum[5].normal[1] = 0 + 0;
6340 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6341 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6347 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6348 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6349 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6350 r_refdef.view.frustum[0].dist = m[15] - m[12];
6352 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6353 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6354 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6355 r_refdef.view.frustum[1].dist = m[15] + m[12];
6357 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6358 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6359 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6360 r_refdef.view.frustum[2].dist = m[15] - m[13];
6362 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6363 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6364 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6365 r_refdef.view.frustum[3].dist = m[15] + m[13];
6367 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6368 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6369 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6370 r_refdef.view.frustum[4].dist = m[15] - m[14];
6372 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6373 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6374 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6375 r_refdef.view.frustum[5].dist = m[15] + m[14];
6378 if (r_refdef.view.useperspective)
6380 slopex = 1.0 / r_refdef.view.frustum_x;
6381 slopey = 1.0 / r_refdef.view.frustum_y;
6382 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6383 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
6384 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
6385 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
6386 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6388 // Leaving those out was a mistake, those were in the old code, and they
6389 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6390 // I couldn't reproduce it after adding those normalizations. --blub
6391 VectorNormalize(r_refdef.view.frustum[0].normal);
6392 VectorNormalize(r_refdef.view.frustum[1].normal);
6393 VectorNormalize(r_refdef.view.frustum[2].normal);
6394 VectorNormalize(r_refdef.view.frustum[3].normal);
6396 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6397 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]);
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[1]);
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[2]);
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[3]);
6402 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6403 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6404 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6405 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6406 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6410 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6411 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6412 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6413 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6414 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6415 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6416 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6417 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6418 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6419 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6421 r_refdef.view.numfrustumplanes = 5;
6423 if (r_refdef.view.useclipplane)
6425 r_refdef.view.numfrustumplanes = 6;
6426 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6429 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6430 PlaneClassify(r_refdef.view.frustum + i);
6432 // LordHavoc: note to all quake engine coders, Quake had a special case
6433 // for 90 degrees which assumed a square view (wrong), so I removed it,
6434 // Quake2 has it disabled as well.
6436 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6437 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6438 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6439 //PlaneClassify(&frustum[0]);
6441 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6442 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6443 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6444 //PlaneClassify(&frustum[1]);
6446 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6447 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6448 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6449 //PlaneClassify(&frustum[2]);
6451 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6452 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6453 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6454 //PlaneClassify(&frustum[3]);
6457 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6458 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6459 //PlaneClassify(&frustum[4]);
6462 void R_View_Update(void)
6464 R_Main_ResizeViewCache();
6465 R_View_SetFrustum();
6466 R_View_WorldVisibility(r_refdef.view.useclipplane);
6467 R_View_UpdateEntityVisible();
6468 R_View_UpdateEntityLighting();
6471 void R_SetupView(qboolean allowwaterclippingplane)
6473 const float *customclipplane = NULL;
6475 if (r_refdef.view.useclipplane && allowwaterclippingplane)
6477 // LordHavoc: couldn't figure out how to make this approach the
6478 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6479 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6480 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6481 dist = r_refdef.view.clipplane.dist;
6482 plane[0] = r_refdef.view.clipplane.normal[0];
6483 plane[1] = r_refdef.view.clipplane.normal[1];
6484 plane[2] = r_refdef.view.clipplane.normal[2];
6486 customclipplane = plane;
6489 if (!r_refdef.view.useperspective)
6490 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);
6491 else if (vid.stencil && r_useinfinitefarclip.integer)
6492 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);
6494 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);
6495 R_SetViewport(&r_refdef.view.viewport);
6498 void R_EntityMatrix(const matrix4x4_t *matrix)
6500 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6502 gl_modelmatrixchanged = false;
6503 gl_modelmatrix = *matrix;
6504 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6505 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6506 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6507 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6509 switch(vid.renderpath)
6511 case RENDERPATH_GL20:
6512 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6513 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6515 case RENDERPATH_CGGL:
6518 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6519 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6522 case RENDERPATH_GL13:
6523 case RENDERPATH_GL11:
6524 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6530 void R_ResetViewRendering2D(void)
6532 r_viewport_t viewport;
6535 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6536 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);
6537 R_SetViewport(&viewport);
6538 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6539 GL_Color(1, 1, 1, 1);
6540 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6541 GL_BlendFunc(GL_ONE, GL_ZERO);
6542 GL_AlphaTest(false);
6543 GL_ScissorTest(false);
6544 GL_DepthMask(false);
6545 GL_DepthRange(0, 1);
6546 GL_DepthTest(false);
6547 R_EntityMatrix(&identitymatrix);
6548 R_Mesh_ResetTextureState();
6549 GL_PolygonOffset(0, 0);
6550 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6551 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6552 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6553 qglStencilMask(~0);CHECKGLERROR
6554 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6555 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6556 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6559 void R_ResetViewRendering3D(void)
6564 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6565 GL_Color(1, 1, 1, 1);
6566 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6567 GL_BlendFunc(GL_ONE, GL_ZERO);
6568 GL_AlphaTest(false);
6569 GL_ScissorTest(true);
6571 GL_DepthRange(0, 1);
6573 R_EntityMatrix(&identitymatrix);
6574 R_Mesh_ResetTextureState();
6575 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6576 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6577 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6578 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6579 qglStencilMask(~0);CHECKGLERROR
6580 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6581 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6582 GL_CullFace(r_refdef.view.cullface_back);
6585 void R_RenderScene(void);
6586 void R_RenderWaterPlanes(void);
6588 static void R_Water_StartFrame(void)
6591 int waterwidth, waterheight, texturewidth, textureheight;
6592 r_waterstate_waterplane_t *p;
6594 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6597 switch(vid.renderpath)
6599 case RENDERPATH_GL20:
6600 case RENDERPATH_CGGL:
6602 case RENDERPATH_GL13:
6603 case RENDERPATH_GL11:
6607 // set waterwidth and waterheight to the water resolution that will be
6608 // used (often less than the screen resolution for faster rendering)
6609 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6610 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6612 // calculate desired texture sizes
6613 // can't use water if the card does not support the texture size
6614 if (!r_water.integer || r_showsurfaces.integer)
6615 texturewidth = textureheight = waterwidth = waterheight = 0;
6616 else if (vid.support.arb_texture_non_power_of_two)
6618 texturewidth = waterwidth;
6619 textureheight = waterheight;
6623 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
6624 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
6627 // allocate textures as needed
6628 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6630 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6631 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6633 if (p->texture_refraction)
6634 R_FreeTexture(p->texture_refraction);
6635 p->texture_refraction = NULL;
6636 if (p->texture_reflection)
6637 R_FreeTexture(p->texture_reflection);
6638 p->texture_reflection = NULL;
6640 memset(&r_waterstate, 0, sizeof(r_waterstate));
6641 r_waterstate.texturewidth = texturewidth;
6642 r_waterstate.textureheight = textureheight;
6645 if (r_waterstate.texturewidth)
6647 r_waterstate.enabled = true;
6649 // when doing a reduced render (HDR) we want to use a smaller area
6650 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6651 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6653 // set up variables that will be used in shader setup
6654 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6655 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6656 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6657 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6660 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6661 r_waterstate.numwaterplanes = 0;
6664 void R_Water_AddWaterPlane(msurface_t *surface)
6666 int triangleindex, planeindex;
6672 r_waterstate_waterplane_t *p;
6673 texture_t *t = R_GetCurrentTexture(surface->texture);
6674 // just use the first triangle with a valid normal for any decisions
6675 VectorClear(normal);
6676 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6678 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6679 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6680 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6681 TriangleNormal(vert[0], vert[1], vert[2], normal);
6682 if (VectorLength2(normal) >= 0.001)
6686 VectorCopy(normal, plane.normal);
6687 VectorNormalize(plane.normal);
6688 plane.dist = DotProduct(vert[0], plane.normal);
6689 PlaneClassify(&plane);
6690 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6692 // skip backfaces (except if nocullface is set)
6693 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6695 VectorNegate(plane.normal, plane.normal);
6697 PlaneClassify(&plane);
6701 // find a matching plane if there is one
6702 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6703 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6705 if (planeindex >= r_waterstate.maxwaterplanes)
6706 return; // nothing we can do, out of planes
6708 // if this triangle does not fit any known plane rendered this frame, add one
6709 if (planeindex >= r_waterstate.numwaterplanes)
6711 // store the new plane
6712 r_waterstate.numwaterplanes++;
6714 // clear materialflags and pvs
6715 p->materialflags = 0;
6716 p->pvsvalid = false;
6718 // merge this surface's materialflags into the waterplane
6719 p->materialflags |= t->currentmaterialflags;
6720 // merge this surface's PVS into the waterplane
6721 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6722 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6723 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6725 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6730 static void R_Water_ProcessPlanes(void)
6732 r_refdef_view_t originalview;
6733 r_refdef_view_t myview;
6735 r_waterstate_waterplane_t *p;
6737 originalview = r_refdef.view;
6739 // make sure enough textures are allocated
6740 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6742 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6744 if (!p->texture_refraction)
6745 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);
6746 if (!p->texture_refraction)
6750 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6752 if (!p->texture_reflection)
6753 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);
6754 if (!p->texture_reflection)
6760 r_refdef.view = originalview;
6761 r_refdef.view.showdebug = false;
6762 r_refdef.view.width = r_waterstate.waterwidth;
6763 r_refdef.view.height = r_waterstate.waterheight;
6764 r_refdef.view.useclipplane = true;
6765 myview = r_refdef.view;
6766 r_waterstate.renderingscene = true;
6767 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6769 // render the normal view scene and copy into texture
6770 // (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)
6771 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6773 r_refdef.view = myview;
6774 r_refdef.view.clipplane = p->plane;
6775 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6776 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6777 PlaneClassify(&r_refdef.view.clipplane);
6779 R_ResetViewRendering3D();
6780 R_ClearScreen(r_refdef.fogenabled);
6784 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);
6787 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6789 r_refdef.view = myview;
6790 // render reflected scene and copy into texture
6791 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6792 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6793 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6794 r_refdef.view.clipplane = p->plane;
6795 // reverse the cullface settings for this render
6796 r_refdef.view.cullface_front = GL_FRONT;
6797 r_refdef.view.cullface_back = GL_BACK;
6798 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6800 r_refdef.view.usecustompvs = true;
6802 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6804 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6807 R_ResetViewRendering3D();
6808 R_ClearScreen(r_refdef.fogenabled);
6812 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);
6815 r_waterstate.renderingscene = false;
6816 r_refdef.view = originalview;
6817 R_ResetViewRendering3D();
6818 R_ClearScreen(r_refdef.fogenabled);
6822 r_refdef.view = originalview;
6823 r_waterstate.renderingscene = false;
6824 Cvar_SetValueQuick(&r_water, 0);
6825 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6829 void R_Bloom_StartFrame(void)
6831 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6833 switch(vid.renderpath)
6835 case RENDERPATH_GL20:
6836 case RENDERPATH_CGGL:
6838 case RENDERPATH_GL13:
6839 case RENDERPATH_GL11:
6843 // set bloomwidth and bloomheight to the bloom resolution that will be
6844 // used (often less than the screen resolution for faster rendering)
6845 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6846 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6847 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6848 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6849 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6851 // calculate desired texture sizes
6852 if (vid.support.arb_texture_non_power_of_two)
6854 screentexturewidth = r_refdef.view.width;
6855 screentextureheight = r_refdef.view.height;
6856 bloomtexturewidth = r_bloomstate.bloomwidth;
6857 bloomtextureheight = r_bloomstate.bloomheight;
6861 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6862 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6863 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
6864 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
6867 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))
6869 Cvar_SetValueQuick(&r_hdr, 0);
6870 Cvar_SetValueQuick(&r_bloom, 0);
6871 Cvar_SetValueQuick(&r_motionblur, 0);
6872 Cvar_SetValueQuick(&r_damageblur, 0);
6875 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)))
6876 screentexturewidth = screentextureheight = 0;
6877 if (!r_hdr.integer && !r_bloom.integer)
6878 bloomtexturewidth = bloomtextureheight = 0;
6880 // allocate textures as needed
6881 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
6883 if (r_bloomstate.texture_screen)
6884 R_FreeTexture(r_bloomstate.texture_screen);
6885 r_bloomstate.texture_screen = NULL;
6886 r_bloomstate.screentexturewidth = screentexturewidth;
6887 r_bloomstate.screentextureheight = screentextureheight;
6888 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6889 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
6891 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
6893 if (r_bloomstate.texture_bloom)
6894 R_FreeTexture(r_bloomstate.texture_bloom);
6895 r_bloomstate.texture_bloom = NULL;
6896 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6897 r_bloomstate.bloomtextureheight = bloomtextureheight;
6898 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6899 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6902 // when doing a reduced render (HDR) we want to use a smaller area
6903 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6904 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6905 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6906 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6907 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6909 // set up a texcoord array for the full resolution screen image
6910 // (we have to keep this around to copy back during final render)
6911 r_bloomstate.screentexcoord2f[0] = 0;
6912 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
6913 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
6914 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
6915 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
6916 r_bloomstate.screentexcoord2f[5] = 0;
6917 r_bloomstate.screentexcoord2f[6] = 0;
6918 r_bloomstate.screentexcoord2f[7] = 0;
6920 // set up a texcoord array for the reduced resolution bloom image
6921 // (which will be additive blended over the screen image)
6922 r_bloomstate.bloomtexcoord2f[0] = 0;
6923 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6924 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6925 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6926 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6927 r_bloomstate.bloomtexcoord2f[5] = 0;
6928 r_bloomstate.bloomtexcoord2f[6] = 0;
6929 r_bloomstate.bloomtexcoord2f[7] = 0;
6931 if (r_hdr.integer || r_bloom.integer)
6933 r_bloomstate.enabled = true;
6934 r_bloomstate.hdr = r_hdr.integer != 0;
6937 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);
6940 void R_Bloom_CopyBloomTexture(float colorscale)
6942 r_refdef.stats.bloom++;
6944 // scale down screen texture to the bloom texture size
6946 R_SetViewport(&r_bloomstate.viewport);
6947 GL_BlendFunc(GL_ONE, GL_ZERO);
6948 GL_Color(colorscale, colorscale, colorscale, 1);
6949 // TODO: optimize with multitexture or GLSL
6950 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
6951 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6952 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
6953 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6955 // we now have a bloom image in the framebuffer
6956 // copy it into the bloom image texture for later processing
6957 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);
6958 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6961 void R_Bloom_CopyHDRTexture(void)
6963 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);
6964 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6967 void R_Bloom_MakeTexture(void)
6970 float xoffset, yoffset, r, brighten;
6972 r_refdef.stats.bloom++;
6974 R_ResetViewRendering2D();
6975 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
6976 R_Mesh_ColorPointer(NULL, 0, 0);
6978 // we have a bloom image in the framebuffer
6980 R_SetViewport(&r_bloomstate.viewport);
6982 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6985 r = bound(0, r_bloom_colorexponent.value / x, 1);
6986 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6987 GL_Color(r, r, r, 1);
6988 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6989 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
6990 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
6991 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6993 // copy the vertically blurred bloom view to a texture
6994 GL_ActiveTexture(0);
6996 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
6997 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7000 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7001 brighten = r_bloom_brighten.value;
7003 brighten *= r_hdr_range.value;
7004 brighten = sqrt(brighten);
7006 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7007 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7008 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7010 for (dir = 0;dir < 2;dir++)
7012 // blend on at multiple vertical offsets to achieve a vertical blur
7013 // TODO: do offset blends using GLSL
7014 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7015 GL_BlendFunc(GL_ONE, GL_ZERO);
7016 for (x = -range;x <= range;x++)
7018 if (!dir){xoffset = 0;yoffset = x;}
7019 else {xoffset = x;yoffset = 0;}
7020 xoffset /= (float)r_bloomstate.bloomtexturewidth;
7021 yoffset /= (float)r_bloomstate.bloomtextureheight;
7022 // compute a texcoord array with the specified x and y offset
7023 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7024 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7025 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7026 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7027 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7028 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7029 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7030 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7031 // this r value looks like a 'dot' particle, fading sharply to
7032 // black at the edges
7033 // (probably not realistic but looks good enough)
7034 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7035 //r = brighten/(range*2+1);
7036 r = brighten / (range * 2 + 1);
7038 r *= (1 - x*x/(float)(range*range));
7039 GL_Color(r, r, r, 1);
7040 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7041 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7042 GL_BlendFunc(GL_ONE, GL_ONE);
7045 // copy the vertically blurred bloom view to a texture
7046 GL_ActiveTexture(0);
7048 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7049 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7052 // apply subtract last
7053 // (just like it would be in a GLSL shader)
7054 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7056 GL_BlendFunc(GL_ONE, GL_ZERO);
7057 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7058 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7059 GL_Color(1, 1, 1, 1);
7060 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7061 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7063 GL_BlendFunc(GL_ONE, GL_ONE);
7064 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7065 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7066 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7067 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7068 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7069 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7070 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7072 // copy the darkened bloom view to a texture
7073 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);
7074 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7078 void R_HDR_RenderBloomTexture(void)
7080 int oldwidth, oldheight;
7081 float oldcolorscale;
7083 oldcolorscale = r_refdef.view.colorscale;
7084 oldwidth = r_refdef.view.width;
7085 oldheight = r_refdef.view.height;
7086 r_refdef.view.width = r_bloomstate.bloomwidth;
7087 r_refdef.view.height = r_bloomstate.bloomheight;
7089 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
7090 // TODO: add exposure compensation features
7091 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7093 r_refdef.view.showdebug = false;
7094 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7096 R_ResetViewRendering3D();
7098 R_ClearScreen(r_refdef.fogenabled);
7099 if (r_timereport_active)
7100 R_TimeReport("HDRclear");
7103 if (r_timereport_active)
7104 R_TimeReport("visibility");
7106 // only do secondary renders with HDR if r_hdr is 2 or higher
7107 r_waterstate.numwaterplanes = 0;
7108 if (r_waterstate.enabled && r_hdr.integer >= 2)
7109 R_RenderWaterPlanes();
7111 r_refdef.view.showdebug = true;
7113 r_waterstate.numwaterplanes = 0;
7115 R_ResetViewRendering2D();
7117 R_Bloom_CopyHDRTexture();
7118 R_Bloom_MakeTexture();
7120 // restore the view settings
7121 r_refdef.view.width = oldwidth;
7122 r_refdef.view.height = oldheight;
7123 r_refdef.view.colorscale = oldcolorscale;
7124 r_frame++; // used only by R_GetCurrentTexture
7126 R_ResetViewRendering3D();
7128 R_ClearScreen(r_refdef.fogenabled);
7129 if (r_timereport_active)
7130 R_TimeReport("viewclear");
7133 static void R_BlendView(void)
7135 unsigned int permutation;
7136 float uservecs[4][4];
7138 switch (vid.renderpath)
7140 case RENDERPATH_GL20:
7141 case RENDERPATH_CGGL:
7143 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7144 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7145 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7146 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7147 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7149 if (r_bloomstate.texture_screen)
7151 // make sure the buffer is available
7152 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7154 R_ResetViewRendering2D();
7155 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7156 R_Mesh_ColorPointer(NULL, 0, 0);
7158 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7160 // declare variables
7162 static float avgspeed;
7164 speed = VectorLength(cl.movement_velocity);
7166 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7167 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7169 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7170 speed = bound(0, speed, 1);
7171 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7173 // calculate values into a standard alpha
7174 cl.motionbluralpha = 1 - exp(-
7176 (r_motionblur.value * speed / 80)
7178 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7181 max(0.0001, cl.time - cl.oldtime) // fps independent
7184 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7185 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7187 if (cl.motionbluralpha > 0)
7189 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7190 GL_Color(1, 1, 1, cl.motionbluralpha);
7191 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7192 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7193 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7194 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7198 // copy view into the screen texture
7199 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);
7200 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7202 else if (!r_bloomstate.texture_bloom)
7204 // we may still have to do view tint...
7205 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7207 // apply a color tint to the whole view
7208 R_ResetViewRendering2D();
7209 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7210 R_Mesh_ColorPointer(NULL, 0, 0);
7211 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7212 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7213 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7214 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7216 break; // no screen processing, no bloom, skip it
7219 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7221 // render simple bloom effect
7222 // copy the screen and shrink it and darken it for the bloom process
7223 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7224 // make the bloom texture
7225 R_Bloom_MakeTexture();
7228 #if _MSC_VER >= 1400
7229 #define sscanf sscanf_s
7231 memset(uservecs, 0, sizeof(uservecs));
7232 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7233 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7234 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7235 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7237 R_ResetViewRendering2D();
7238 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7239 R_Mesh_ColorPointer(NULL, 0, 0);
7240 GL_Color(1, 1, 1, 1);
7241 GL_BlendFunc(GL_ONE, GL_ZERO);
7242 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7243 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7245 switch(vid.renderpath)
7247 case RENDERPATH_GL20:
7248 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7249 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(r_bloomstate.texture_screen));
7250 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , R_GetTexture(r_bloomstate.texture_bloom ));
7251 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps ));
7252 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]);
7253 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime , cl.time);
7254 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7255 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]);
7256 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]);
7257 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]);
7258 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]);
7259 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7261 case RENDERPATH_CGGL:
7263 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7264 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , R_GetTexture(r_bloomstate.texture_screen));CHECKCGERROR
7265 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , R_GetTexture(r_bloomstate.texture_bloom ));CHECKCGERROR
7266 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, R_GetTexture(r_texture_gammaramps ));CHECKCGERROR
7267 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
7268 if (r_cg_permutation->fp_ClientTime ) cgGLSetParameter1f( r_cg_permutation->fp_ClientTime , cl.time);CHECKCGERROR
7269 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7270 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
7271 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
7272 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
7273 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
7274 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
7280 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7281 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7283 case RENDERPATH_GL13:
7284 case RENDERPATH_GL11:
7285 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7287 // apply a color tint to the whole view
7288 R_ResetViewRendering2D();
7289 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7290 R_Mesh_ColorPointer(NULL, 0, 0);
7291 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7292 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7293 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7294 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7300 matrix4x4_t r_waterscrollmatrix;
7302 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7304 if (r_refdef.fog_density)
7306 r_refdef.fogcolor[0] = r_refdef.fog_red;
7307 r_refdef.fogcolor[1] = r_refdef.fog_green;
7308 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7310 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7311 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7312 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7313 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7317 VectorCopy(r_refdef.fogcolor, fogvec);
7318 // color.rgb *= ContrastBoost * SceneBrightness;
7319 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7320 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7321 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7322 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7327 void R_UpdateVariables(void)
7331 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7333 r_refdef.farclip = r_farclip_base.value;
7334 if (r_refdef.scene.worldmodel)
7335 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7336 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7338 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7339 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7340 r_refdef.polygonfactor = 0;
7341 r_refdef.polygonoffset = 0;
7342 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7343 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7345 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7346 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7347 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7348 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7349 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7350 if (r_showsurfaces.integer)
7352 r_refdef.scene.rtworld = false;
7353 r_refdef.scene.rtworldshadows = false;
7354 r_refdef.scene.rtdlight = false;
7355 r_refdef.scene.rtdlightshadows = false;
7356 r_refdef.lightmapintensity = 0;
7359 if (gamemode == GAME_NEHAHRA)
7361 if (gl_fogenable.integer)
7363 r_refdef.oldgl_fogenable = true;
7364 r_refdef.fog_density = gl_fogdensity.value;
7365 r_refdef.fog_red = gl_fogred.value;
7366 r_refdef.fog_green = gl_foggreen.value;
7367 r_refdef.fog_blue = gl_fogblue.value;
7368 r_refdef.fog_alpha = 1;
7369 r_refdef.fog_start = 0;
7370 r_refdef.fog_end = gl_skyclip.value;
7371 r_refdef.fog_height = 1<<30;
7372 r_refdef.fog_fadedepth = 128;
7374 else if (r_refdef.oldgl_fogenable)
7376 r_refdef.oldgl_fogenable = false;
7377 r_refdef.fog_density = 0;
7378 r_refdef.fog_red = 0;
7379 r_refdef.fog_green = 0;
7380 r_refdef.fog_blue = 0;
7381 r_refdef.fog_alpha = 0;
7382 r_refdef.fog_start = 0;
7383 r_refdef.fog_end = 0;
7384 r_refdef.fog_height = 1<<30;
7385 r_refdef.fog_fadedepth = 128;
7389 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7390 r_refdef.fog_start = max(0, r_refdef.fog_start);
7391 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7393 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7395 if (r_refdef.fog_density && r_drawfog.integer)
7397 r_refdef.fogenabled = true;
7398 // this is the point where the fog reaches 0.9986 alpha, which we
7399 // consider a good enough cutoff point for the texture
7400 // (0.9986 * 256 == 255.6)
7401 if (r_fog_exp2.integer)
7402 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7404 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7405 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7406 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7407 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7408 // fog color was already set
7409 // update the fog texture
7410 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)
7411 R_BuildFogTexture();
7414 r_refdef.fogenabled = false;
7416 switch(vid.renderpath)
7418 case RENDERPATH_GL20:
7419 case RENDERPATH_CGGL:
7420 if(v_glslgamma.integer && !vid_gammatables_trivial)
7422 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7424 // build GLSL gamma texture
7425 #define RAMPWIDTH 256
7426 unsigned short ramp[RAMPWIDTH * 3];
7427 unsigned char rampbgr[RAMPWIDTH][4];
7430 r_texture_gammaramps_serial = vid_gammatables_serial;
7432 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7433 for(i = 0; i < RAMPWIDTH; ++i)
7435 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7436 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7437 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7440 if (r_texture_gammaramps)
7442 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7446 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);
7452 // remove GLSL gamma texture
7455 case RENDERPATH_GL13:
7456 case RENDERPATH_GL11:
7461 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7462 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7468 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7469 if( scenetype != r_currentscenetype ) {
7470 // store the old scenetype
7471 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7472 r_currentscenetype = scenetype;
7473 // move in the new scene
7474 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7483 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7485 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7486 if( scenetype == r_currentscenetype ) {
7487 return &r_refdef.scene;
7489 return &r_scenes_store[ scenetype ];
7498 void R_RenderView(void)
7500 if (r_timereport_active)
7501 R_TimeReport("start");
7502 r_frame++; // used only by R_GetCurrentTexture
7503 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7505 if (!r_drawentities.integer)
7506 r_refdef.scene.numentities = 0;
7508 R_AnimCache_ClearCache();
7509 R_FrameData_NewFrame();
7511 if (r_refdef.view.isoverlay)
7513 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7514 GL_Clear( GL_DEPTH_BUFFER_BIT );
7515 R_TimeReport("depthclear");
7517 r_refdef.view.showdebug = false;
7519 r_waterstate.enabled = false;
7520 r_waterstate.numwaterplanes = 0;
7528 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7529 return; //Host_Error ("R_RenderView: NULL worldmodel");
7531 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7533 // break apart the view matrix into vectors for various purposes
7534 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7535 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7536 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7537 VectorNegate(r_refdef.view.left, r_refdef.view.right);
7538 // make an inverted copy of the view matrix for tracking sprites
7539 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7541 R_Shadow_UpdateWorldLightSelection();
7543 R_Bloom_StartFrame();
7544 R_Water_StartFrame();
7547 if (r_timereport_active)
7548 R_TimeReport("viewsetup");
7550 R_ResetViewRendering3D();
7552 if (r_refdef.view.clear || r_refdef.fogenabled)
7554 R_ClearScreen(r_refdef.fogenabled);
7555 if (r_timereport_active)
7556 R_TimeReport("viewclear");
7558 r_refdef.view.clear = true;
7560 // this produces a bloom texture to be used in R_BlendView() later
7561 if (r_hdr.integer && r_bloomstate.bloomwidth)
7562 R_HDR_RenderBloomTexture();
7564 r_refdef.view.showdebug = true;
7567 if (r_timereport_active)
7568 R_TimeReport("visibility");
7570 r_waterstate.numwaterplanes = 0;
7571 if (r_waterstate.enabled)
7572 R_RenderWaterPlanes();
7575 r_waterstate.numwaterplanes = 0;
7578 if (r_timereport_active)
7579 R_TimeReport("blendview");
7581 GL_Scissor(0, 0, vid.width, vid.height);
7582 GL_ScissorTest(false);
7586 void R_RenderWaterPlanes(void)
7588 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7590 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7591 if (r_timereport_active)
7592 R_TimeReport("waterworld");
7595 // don't let sound skip if going slow
7596 if (r_refdef.scene.extraupdate)
7599 R_DrawModelsAddWaterPlanes();
7600 if (r_timereport_active)
7601 R_TimeReport("watermodels");
7603 if (r_waterstate.numwaterplanes)
7605 R_Water_ProcessPlanes();
7606 if (r_timereport_active)
7607 R_TimeReport("waterscenes");
7611 extern void R_DrawLightningBeams (void);
7612 extern void VM_CL_AddPolygonsToMeshQueue (void);
7613 extern void R_DrawPortals (void);
7614 extern cvar_t cl_locs_show;
7615 static void R_DrawLocs(void);
7616 static void R_DrawEntityBBoxes(void);
7617 static void R_DrawModelDecals(void);
7618 extern cvar_t cl_decals_newsystem;
7619 extern qboolean r_shadow_usingdeferredprepass;
7620 void R_RenderScene(void)
7622 r_refdef.stats.renders++;
7626 // don't let sound skip if going slow
7627 if (r_refdef.scene.extraupdate)
7630 R_MeshQueue_BeginScene();
7634 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);
7636 if (cl.csqc_vidvars.drawworld)
7638 // don't let sound skip if going slow
7639 if (r_refdef.scene.extraupdate)
7642 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7644 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7645 if (r_timereport_active)
7646 R_TimeReport("worldsky");
7649 if (R_DrawBrushModelsSky() && r_timereport_active)
7650 R_TimeReport("bmodelsky");
7652 if (skyrendermasked && skyrenderlater)
7654 // we have to force off the water clipping plane while rendering sky
7658 if (r_timereport_active)
7659 R_TimeReport("sky");
7663 R_AnimCache_CacheVisibleEntities();
7664 if (r_timereport_active)
7665 R_TimeReport("animation");
7667 R_Shadow_PrepareLights();
7668 if (r_timereport_active)
7669 R_TimeReport("preparelights");
7671 if (r_shadow_usingdeferredprepass)
7672 R_Shadow_DrawPrepass();
7674 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7676 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7677 if (r_timereport_active)
7678 R_TimeReport("worlddepth");
7680 if (r_depthfirst.integer >= 2)
7682 R_DrawModelsDepth();
7683 if (r_timereport_active)
7684 R_TimeReport("modeldepth");
7687 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7689 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7690 if (r_timereport_active)
7691 R_TimeReport("world");
7694 // don't let sound skip if going slow
7695 if (r_refdef.scene.extraupdate)
7699 if (r_timereport_active)
7700 R_TimeReport("models");
7702 // don't let sound skip if going slow
7703 if (r_refdef.scene.extraupdate)
7706 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7708 R_DrawModelShadows();
7709 R_ResetViewRendering3D();
7710 // don't let sound skip if going slow
7711 if (r_refdef.scene.extraupdate)
7715 if (!r_shadow_usingdeferredprepass)
7717 R_Shadow_DrawLights();
7718 if (r_timereport_active)
7719 R_TimeReport("rtlights");
7722 // don't let sound skip if going slow
7723 if (r_refdef.scene.extraupdate)
7726 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7728 R_DrawModelShadows();
7729 R_ResetViewRendering3D();
7730 // don't let sound skip if going slow
7731 if (r_refdef.scene.extraupdate)
7735 if (cl.csqc_vidvars.drawworld)
7737 if (cl_decals_newsystem.integer)
7739 R_DrawModelDecals();
7740 if (r_timereport_active)
7741 R_TimeReport("modeldecals");
7746 if (r_timereport_active)
7747 R_TimeReport("decals");
7751 if (r_timereport_active)
7752 R_TimeReport("particles");
7755 if (r_timereport_active)
7756 R_TimeReport("explosions");
7758 R_DrawLightningBeams();
7759 if (r_timereport_active)
7760 R_TimeReport("lightning");
7763 VM_CL_AddPolygonsToMeshQueue();
7765 if (r_refdef.view.showdebug)
7767 if (cl_locs_show.integer)
7770 if (r_timereport_active)
7771 R_TimeReport("showlocs");
7774 if (r_drawportals.integer)
7777 if (r_timereport_active)
7778 R_TimeReport("portals");
7781 if (r_showbboxes.value > 0)
7783 R_DrawEntityBBoxes();
7784 if (r_timereport_active)
7785 R_TimeReport("bboxes");
7789 R_MeshQueue_RenderTransparent();
7790 if (r_timereport_active)
7791 R_TimeReport("drawtrans");
7793 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))
7795 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7796 if (r_timereport_active)
7797 R_TimeReport("worlddebug");
7798 R_DrawModelsDebug();
7799 if (r_timereport_active)
7800 R_TimeReport("modeldebug");
7803 if (cl.csqc_vidvars.drawworld)
7805 R_Shadow_DrawCoronas();
7806 if (r_timereport_active)
7807 R_TimeReport("coronas");
7810 // don't let sound skip if going slow
7811 if (r_refdef.scene.extraupdate)
7814 R_ResetViewRendering2D();
7817 static const unsigned short bboxelements[36] =
7827 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7830 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7832 RSurf_ActiveWorldEntity();
7834 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7835 GL_DepthMask(false);
7836 GL_DepthRange(0, 1);
7837 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7838 R_Mesh_ResetTextureState();
7840 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7841 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7842 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7843 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7844 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7845 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7846 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7847 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7848 R_FillColors(color4f, 8, cr, cg, cb, ca);
7849 if (r_refdef.fogenabled)
7851 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7853 f1 = RSurf_FogVertex(v);
7855 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7856 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7857 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7860 R_Mesh_VertexPointer(vertex3f, 0, 0);
7861 R_Mesh_ColorPointer(color4f, 0, 0);
7862 R_Mesh_ResetTextureState();
7863 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7864 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
7867 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7871 prvm_edict_t *edict;
7872 prvm_prog_t *prog_save = prog;
7874 // this function draws bounding boxes of server entities
7878 GL_CullFace(GL_NONE);
7879 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7883 for (i = 0;i < numsurfaces;i++)
7885 edict = PRVM_EDICT_NUM(surfacelist[i]);
7886 switch ((int)edict->fields.server->solid)
7888 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7889 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7890 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7891 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7892 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7893 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7895 color[3] *= r_showbboxes.value;
7896 color[3] = bound(0, color[3], 1);
7897 GL_DepthTest(!r_showdisabledepthtest.integer);
7898 GL_CullFace(r_refdef.view.cullface_front);
7899 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7905 static void R_DrawEntityBBoxes(void)
7908 prvm_edict_t *edict;
7910 prvm_prog_t *prog_save = prog;
7912 // this function draws bounding boxes of server entities
7918 for (i = 0;i < prog->num_edicts;i++)
7920 edict = PRVM_EDICT_NUM(i);
7921 if (edict->priv.server->free)
7923 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7924 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7926 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7928 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7929 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7935 static const int nomodelelement3i[24] =
7947 static const unsigned short nomodelelement3s[24] =
7959 static const float nomodelvertex3f[6*3] =
7969 static const float nomodelcolor4f[6*4] =
7971 0.0f, 0.0f, 0.5f, 1.0f,
7972 0.0f, 0.0f, 0.5f, 1.0f,
7973 0.0f, 0.5f, 0.0f, 1.0f,
7974 0.0f, 0.5f, 0.0f, 1.0f,
7975 0.5f, 0.0f, 0.0f, 1.0f,
7976 0.5f, 0.0f, 0.0f, 1.0f
7979 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7985 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);
7987 // this is only called once per entity so numsurfaces is always 1, and
7988 // surfacelist is always {0}, so this code does not handle batches
7990 if (rsurface.ent_flags & RENDER_ADDITIVE)
7992 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7993 GL_DepthMask(false);
7995 else if (rsurface.colormod[3] < 1)
7997 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7998 GL_DepthMask(false);
8002 GL_BlendFunc(GL_ONE, GL_ZERO);
8005 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8006 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8007 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8008 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8009 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8010 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8011 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8012 R_Mesh_ColorPointer(color4f, 0, 0);
8013 for (i = 0, c = color4f;i < 6;i++, c += 4)
8015 c[0] *= rsurface.colormod[0];
8016 c[1] *= rsurface.colormod[1];
8017 c[2] *= rsurface.colormod[2];
8018 c[3] *= rsurface.colormod[3];
8020 if (r_refdef.fogenabled)
8022 for (i = 0, c = color4f;i < 6;i++, c += 4)
8024 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8026 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8027 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8028 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8031 R_Mesh_ResetTextureState();
8032 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8035 void R_DrawNoModel(entity_render_t *ent)
8038 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8039 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8040 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8042 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8045 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8047 vec3_t right1, right2, diff, normal;
8049 VectorSubtract (org2, org1, normal);
8051 // calculate 'right' vector for start
8052 VectorSubtract (r_refdef.view.origin, org1, diff);
8053 CrossProduct (normal, diff, right1);
8054 VectorNormalize (right1);
8056 // calculate 'right' vector for end
8057 VectorSubtract (r_refdef.view.origin, org2, diff);
8058 CrossProduct (normal, diff, right2);
8059 VectorNormalize (right2);
8061 vert[ 0] = org1[0] + width * right1[0];
8062 vert[ 1] = org1[1] + width * right1[1];
8063 vert[ 2] = org1[2] + width * right1[2];
8064 vert[ 3] = org1[0] - width * right1[0];
8065 vert[ 4] = org1[1] - width * right1[1];
8066 vert[ 5] = org1[2] - width * right1[2];
8067 vert[ 6] = org2[0] - width * right2[0];
8068 vert[ 7] = org2[1] - width * right2[1];
8069 vert[ 8] = org2[2] - width * right2[2];
8070 vert[ 9] = org2[0] + width * right2[0];
8071 vert[10] = org2[1] + width * right2[1];
8072 vert[11] = org2[2] + width * right2[2];
8075 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)
8077 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8078 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8079 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8080 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8081 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8082 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8083 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8084 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8085 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8086 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8087 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8088 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8091 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8096 VectorSet(v, x, y, z);
8097 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8098 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8100 if (i == mesh->numvertices)
8102 if (mesh->numvertices < mesh->maxvertices)
8104 VectorCopy(v, vertex3f);
8105 mesh->numvertices++;
8107 return mesh->numvertices;
8113 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8117 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8118 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8119 e = mesh->element3i + mesh->numtriangles * 3;
8120 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8122 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8123 if (mesh->numtriangles < mesh->maxtriangles)
8128 mesh->numtriangles++;
8130 element[1] = element[2];
8134 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8138 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8139 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8140 e = mesh->element3i + mesh->numtriangles * 3;
8141 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8143 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8144 if (mesh->numtriangles < mesh->maxtriangles)
8149 mesh->numtriangles++;
8151 element[1] = element[2];
8155 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8156 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8158 int planenum, planenum2;
8161 mplane_t *plane, *plane2;
8163 double temppoints[2][256*3];
8164 // figure out how large a bounding box we need to properly compute this brush
8166 for (w = 0;w < numplanes;w++)
8167 maxdist = max(maxdist, fabs(planes[w].dist));
8168 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8169 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8170 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8174 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8175 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8177 if (planenum2 == planenum)
8179 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);
8182 if (tempnumpoints < 3)
8184 // generate elements forming a triangle fan for this polygon
8185 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8189 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)
8191 texturelayer_t *layer;
8192 layer = t->currentlayers + t->currentnumlayers++;
8194 layer->depthmask = depthmask;
8195 layer->blendfunc1 = blendfunc1;
8196 layer->blendfunc2 = blendfunc2;
8197 layer->texture = texture;
8198 layer->texmatrix = *matrix;
8199 layer->color[0] = r;
8200 layer->color[1] = g;
8201 layer->color[2] = b;
8202 layer->color[3] = a;
8205 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8208 index = parms[2] + r_refdef.scene.time * parms[3];
8209 index -= floor(index);
8213 case Q3WAVEFUNC_NONE:
8214 case Q3WAVEFUNC_NOISE:
8215 case Q3WAVEFUNC_COUNT:
8218 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8219 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8220 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8221 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8222 case Q3WAVEFUNC_TRIANGLE:
8224 f = index - floor(index);
8235 return (float)(parms[0] + parms[1] * f);
8238 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8243 matrix4x4_t matrix, temp;
8244 switch(tcmod->tcmod)
8248 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8249 matrix = r_waterscrollmatrix;
8251 matrix = identitymatrix;
8253 case Q3TCMOD_ENTITYTRANSLATE:
8254 // this is used in Q3 to allow the gamecode to control texcoord
8255 // scrolling on the entity, which is not supported in darkplaces yet.
8256 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8258 case Q3TCMOD_ROTATE:
8259 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8260 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8261 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8264 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8266 case Q3TCMOD_SCROLL:
8267 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8269 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8270 w = (int) tcmod->parms[0];
8271 h = (int) tcmod->parms[1];
8272 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8274 idx = (int) floor(f * w * h);
8275 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8277 case Q3TCMOD_STRETCH:
8278 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8279 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8281 case Q3TCMOD_TRANSFORM:
8282 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8283 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8284 VectorSet(tcmat + 6, 0 , 0 , 1);
8285 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8286 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8288 case Q3TCMOD_TURBULENT:
8289 // this is handled in the RSurf_PrepareVertices function
8290 matrix = identitymatrix;
8294 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8297 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8299 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8300 char name[MAX_QPATH];
8301 skinframe_t *skinframe;
8302 unsigned char pixels[296*194];
8303 strlcpy(cache->name, skinname, sizeof(cache->name));
8304 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8305 if (developer_loading.integer)
8306 Con_Printf("loading %s\n", name);
8307 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8308 if (!skinframe || !skinframe->base)
8311 fs_offset_t filesize;
8313 f = FS_LoadFile(name, tempmempool, true, &filesize);
8316 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8317 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8321 cache->skinframe = skinframe;
8324 texture_t *R_GetCurrentTexture(texture_t *t)
8327 const entity_render_t *ent = rsurface.entity;
8328 dp_model_t *model = ent->model;
8329 q3shaderinfo_layer_tcmod_t *tcmod;
8331 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
8332 return t->currentframe;
8333 t->update_lastrenderframe = r_frame;
8334 t->update_lastrenderentity = (void *)ent;
8336 // switch to an alternate material if this is a q1bsp animated material
8338 texture_t *texture = t;
8339 int s = rsurface.ent_skinnum;
8340 if ((unsigned int)s >= (unsigned int)model->numskins)
8342 if (model->skinscenes)
8344 if (model->skinscenes[s].framecount > 1)
8345 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8347 s = model->skinscenes[s].firstframe;
8350 t = t + s * model->num_surfaces;
8353 // use an alternate animation if the entity's frame is not 0,
8354 // and only if the texture has an alternate animation
8355 if (rsurface.ent_alttextures && t->anim_total[1])
8356 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8358 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8360 texture->currentframe = t;
8363 // update currentskinframe to be a qw skin or animation frame
8364 if (rsurface.ent_qwskin >= 0)
8366 i = rsurface.ent_qwskin;
8367 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8369 r_qwskincache_size = cl.maxclients;
8371 Mem_Free(r_qwskincache);
8372 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8374 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8375 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8376 t->currentskinframe = r_qwskincache[i].skinframe;
8377 if (t->currentskinframe == NULL)
8378 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8380 else if (t->numskinframes >= 2)
8381 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8382 if (t->backgroundnumskinframes >= 2)
8383 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8385 t->currentmaterialflags = t->basematerialflags;
8386 t->currentalpha = rsurface.colormod[3];
8387 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8388 t->currentalpha *= r_wateralpha.value;
8389 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8390 t->currentalpha *= t->r_water_wateralpha;
8391 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8392 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8393 if (!(rsurface.ent_flags & RENDER_LIGHT))
8394 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8395 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8397 // pick a model lighting mode
8398 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8399 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8401 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8403 if (rsurface.ent_flags & RENDER_ADDITIVE)
8404 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8405 else if (t->currentalpha < 1)
8406 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8407 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8408 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8409 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8410 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8411 if (t->backgroundnumskinframes)
8412 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8413 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8415 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8416 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8419 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8420 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8421 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8423 // there is no tcmod
8424 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8426 t->currenttexmatrix = r_waterscrollmatrix;
8427 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8429 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8431 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8432 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8435 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8436 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8437 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8438 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8440 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8441 if (t->currentskinframe->qpixels)
8442 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8443 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8444 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8445 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8446 t->nmaptexture = t->currentskinframe->nmap;
8447 t->glosstexture = r_texture_black;
8448 t->glowtexture = t->currentskinframe->glow;
8449 t->fogtexture = t->currentskinframe->fog;
8450 if (t->backgroundnumskinframes)
8452 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8453 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8454 t->backgroundglosstexture = r_texture_black;
8455 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8459 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8460 t->backgroundnmaptexture = r_texture_blanknormalmap;
8461 t->backgroundglosstexture = r_texture_black;
8462 t->backgroundglowtexture = NULL;
8464 t->specularpower = r_shadow_glossexponent.value;
8465 // TODO: store reference values for these in the texture?
8466 t->specularscale = 0;
8467 if (r_shadow_gloss.integer > 0)
8469 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8471 if (r_shadow_glossintensity.value > 0)
8473 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8474 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8475 t->specularscale = r_shadow_glossintensity.value;
8478 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8480 t->glosstexture = r_texture_white;
8481 t->backgroundglosstexture = r_texture_white;
8482 t->specularscale = r_shadow_gloss2intensity.value;
8483 t->specularpower = r_shadow_gloss2exponent.value;
8486 t->specularscale *= t->specularscalemod;
8487 t->specularpower *= t->specularpowermod;
8489 // lightmaps mode looks bad with dlights using actual texturing, so turn
8490 // off the colormap and glossmap, but leave the normalmap on as it still
8491 // accurately represents the shading involved
8492 if (gl_lightmaps.integer)
8494 t->basetexture = r_texture_grey128;
8495 t->pantstexture = r_texture_black;
8496 t->shirttexture = r_texture_black;
8497 t->nmaptexture = r_texture_blanknormalmap;
8498 t->glosstexture = r_texture_black;
8499 t->glowtexture = NULL;
8500 t->fogtexture = NULL;
8501 t->backgroundbasetexture = NULL;
8502 t->backgroundnmaptexture = r_texture_blanknormalmap;
8503 t->backgroundglosstexture = r_texture_black;
8504 t->backgroundglowtexture = NULL;
8505 t->specularscale = 0;
8506 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8509 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8510 VectorClear(t->dlightcolor);
8511 t->currentnumlayers = 0;
8512 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8514 int blendfunc1, blendfunc2;
8516 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8518 blendfunc1 = GL_SRC_ALPHA;
8519 blendfunc2 = GL_ONE;
8521 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8523 blendfunc1 = GL_SRC_ALPHA;
8524 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8526 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8528 blendfunc1 = t->customblendfunc[0];
8529 blendfunc2 = t->customblendfunc[1];
8533 blendfunc1 = GL_ONE;
8534 blendfunc2 = GL_ZERO;
8536 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8537 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8539 // fullbright is not affected by r_refdef.lightmapintensity
8540 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]);
8541 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8542 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]);
8543 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8544 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]);
8548 vec3_t ambientcolor;
8550 // set the color tint used for lights affecting this surface
8551 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8553 // q3bsp has no lightmap updates, so the lightstylevalue that
8554 // would normally be baked into the lightmap must be
8555 // applied to the color
8556 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8557 if (model->type == mod_brushq3)
8558 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8559 colorscale *= r_refdef.lightmapintensity;
8560 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8561 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8562 // basic lit geometry
8563 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]);
8564 // add pants/shirt if needed
8565 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8566 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]);
8567 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8568 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]);
8569 // now add ambient passes if needed
8570 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8572 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]);
8573 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8574 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]);
8575 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8576 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]);
8579 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8580 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]);
8581 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8583 // if this is opaque use alpha blend which will darken the earlier
8586 // if this is an alpha blended material, all the earlier passes
8587 // were darkened by fog already, so we only need to add the fog
8588 // color ontop through the fog mask texture
8590 // if this is an additive blended material, all the earlier passes
8591 // were darkened by fog already, and we should not add fog color
8592 // (because the background was not darkened, there is no fog color
8593 // that was lost behind it).
8594 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]);
8598 return t->currentframe;
8601 rsurfacestate_t rsurface;
8603 void R_Mesh_ResizeArrays(int newvertices)
8606 if (rsurface.array_size >= newvertices)
8608 if (rsurface.array_modelvertex3f)
8609 Mem_Free(rsurface.array_modelvertex3f);
8610 rsurface.array_size = (newvertices + 1023) & ~1023;
8611 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8612 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
8613 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
8614 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
8615 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
8616 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
8617 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8618 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8619 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
8620 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
8621 rsurface.array_color4f = base + rsurface.array_size * 27;
8622 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8625 void RSurf_ActiveWorldEntity(void)
8627 dp_model_t *model = r_refdef.scene.worldmodel;
8628 //if (rsurface.entity == r_refdef.scene.worldentity)
8630 rsurface.entity = r_refdef.scene.worldentity;
8631 rsurface.skeleton = NULL;
8632 rsurface.ent_skinnum = 0;
8633 rsurface.ent_qwskin = -1;
8634 rsurface.ent_shadertime = 0;
8635 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8636 if (rsurface.array_size < model->surfmesh.num_vertices)
8637 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8638 rsurface.matrix = identitymatrix;
8639 rsurface.inversematrix = identitymatrix;
8640 rsurface.matrixscale = 1;
8641 rsurface.inversematrixscale = 1;
8642 R_EntityMatrix(&identitymatrix);
8643 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8644 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8645 rsurface.fograngerecip = r_refdef.fograngerecip;
8646 rsurface.fogheightfade = r_refdef.fogheightfade;
8647 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8648 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8649 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8650 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8651 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8652 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8653 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8654 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8655 rsurface.colormod[3] = 1;
8656 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);
8657 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8658 rsurface.frameblend[0].lerp = 1;
8659 rsurface.ent_alttextures = false;
8660 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8661 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8662 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8663 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8664 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8665 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8666 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8667 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8668 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8669 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8670 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8671 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8672 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8673 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8674 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8675 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8676 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8677 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8678 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8679 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8680 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8681 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8682 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8683 rsurface.modelelement3i = model->surfmesh.data_element3i;
8684 rsurface.modelelement3s = model->surfmesh.data_element3s;
8685 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8686 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8687 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8688 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8689 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8690 rsurface.modelsurfaces = model->data_surfaces;
8691 rsurface.generatedvertex = false;
8692 rsurface.vertex3f = rsurface.modelvertex3f;
8693 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8694 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8695 rsurface.svector3f = rsurface.modelsvector3f;
8696 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8697 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8698 rsurface.tvector3f = rsurface.modeltvector3f;
8699 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8700 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8701 rsurface.normal3f = rsurface.modelnormal3f;
8702 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8703 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8704 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8707 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8709 dp_model_t *model = ent->model;
8710 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8712 rsurface.entity = (entity_render_t *)ent;
8713 rsurface.skeleton = ent->skeleton;
8714 rsurface.ent_skinnum = ent->skinnum;
8715 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;
8716 rsurface.ent_shadertime = ent->shadertime;
8717 rsurface.ent_flags = ent->flags;
8718 if (rsurface.array_size < model->surfmesh.num_vertices)
8719 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8720 rsurface.matrix = ent->matrix;
8721 rsurface.inversematrix = ent->inversematrix;
8722 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8723 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8724 R_EntityMatrix(&rsurface.matrix);
8725 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8726 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8727 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8728 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8729 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8730 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8731 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8732 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8733 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8734 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8735 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8736 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8737 rsurface.colormod[3] = ent->alpha;
8738 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8739 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8740 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8741 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8742 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8743 if (ent->model->brush.submodel && !prepass)
8745 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8746 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8748 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8750 if (ent->animcache_vertex3f && !r_framedata_failed)
8752 rsurface.modelvertex3f = ent->animcache_vertex3f;
8753 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8754 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8755 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8757 else if (wanttangents)
8759 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8760 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
8761 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
8762 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8763 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
8765 else if (wantnormals)
8767 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8768 rsurface.modelsvector3f = NULL;
8769 rsurface.modeltvector3f = NULL;
8770 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8771 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
8775 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8776 rsurface.modelsvector3f = NULL;
8777 rsurface.modeltvector3f = NULL;
8778 rsurface.modelnormal3f = NULL;
8779 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
8781 rsurface.modelvertex3f_bufferobject = 0;
8782 rsurface.modelvertex3f_bufferoffset = 0;
8783 rsurface.modelsvector3f_bufferobject = 0;
8784 rsurface.modelsvector3f_bufferoffset = 0;
8785 rsurface.modeltvector3f_bufferobject = 0;
8786 rsurface.modeltvector3f_bufferoffset = 0;
8787 rsurface.modelnormal3f_bufferobject = 0;
8788 rsurface.modelnormal3f_bufferoffset = 0;
8789 rsurface.generatedvertex = true;
8793 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8794 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8795 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8796 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8797 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8798 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8799 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8800 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8801 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8802 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8803 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8804 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8805 rsurface.generatedvertex = false;
8807 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8808 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8809 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8810 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8811 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8812 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8813 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8814 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8815 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8816 rsurface.modelelement3i = model->surfmesh.data_element3i;
8817 rsurface.modelelement3s = model->surfmesh.data_element3s;
8818 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8819 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8820 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8821 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8822 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8823 rsurface.modelsurfaces = model->data_surfaces;
8824 rsurface.vertex3f = rsurface.modelvertex3f;
8825 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8826 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8827 rsurface.svector3f = rsurface.modelsvector3f;
8828 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8829 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8830 rsurface.tvector3f = rsurface.modeltvector3f;
8831 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8832 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8833 rsurface.normal3f = rsurface.modelnormal3f;
8834 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8835 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8836 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8839 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)
8841 rsurface.entity = r_refdef.scene.worldentity;
8842 rsurface.skeleton = NULL;
8843 rsurface.ent_skinnum = 0;
8844 rsurface.ent_qwskin = -1;
8845 rsurface.ent_shadertime = shadertime;
8846 rsurface.ent_flags = entflags;
8847 rsurface.modelnum_vertices = numvertices;
8848 rsurface.modelnum_triangles = numtriangles;
8849 if (rsurface.array_size < rsurface.modelnum_vertices)
8850 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
8851 rsurface.matrix = *matrix;
8852 rsurface.inversematrix = *inversematrix;
8853 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8854 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8855 R_EntityMatrix(&rsurface.matrix);
8856 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8857 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8858 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8859 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8860 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8861 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8862 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8863 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8864 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8865 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8866 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8867 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8868 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);
8869 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8870 rsurface.frameblend[0].lerp = 1;
8871 rsurface.ent_alttextures = false;
8872 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8873 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8876 rsurface.modelvertex3f = vertex3f;
8877 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
8878 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
8879 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8881 else if (wantnormals)
8883 rsurface.modelvertex3f = vertex3f;
8884 rsurface.modelsvector3f = NULL;
8885 rsurface.modeltvector3f = NULL;
8886 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8890 rsurface.modelvertex3f = vertex3f;
8891 rsurface.modelsvector3f = NULL;
8892 rsurface.modeltvector3f = NULL;
8893 rsurface.modelnormal3f = NULL;
8895 rsurface.modelvertex3f_bufferobject = 0;
8896 rsurface.modelvertex3f_bufferoffset = 0;
8897 rsurface.modelsvector3f_bufferobject = 0;
8898 rsurface.modelsvector3f_bufferoffset = 0;
8899 rsurface.modeltvector3f_bufferobject = 0;
8900 rsurface.modeltvector3f_bufferoffset = 0;
8901 rsurface.modelnormal3f_bufferobject = 0;
8902 rsurface.modelnormal3f_bufferoffset = 0;
8903 rsurface.generatedvertex = true;
8904 rsurface.modellightmapcolor4f = color4f;
8905 rsurface.modellightmapcolor4f_bufferobject = 0;
8906 rsurface.modellightmapcolor4f_bufferoffset = 0;
8907 rsurface.modeltexcoordtexture2f = texcoord2f;
8908 rsurface.modeltexcoordtexture2f_bufferobject = 0;
8909 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8910 rsurface.modeltexcoordlightmap2f = NULL;
8911 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
8912 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8913 rsurface.modelelement3i = element3i;
8914 rsurface.modelelement3s = element3s;
8915 rsurface.modelelement3i_bufferobject = 0;
8916 rsurface.modelelement3s_bufferobject = 0;
8917 rsurface.modellightmapoffsets = NULL;
8918 rsurface.modelsurfaces = NULL;
8919 rsurface.vertex3f = rsurface.modelvertex3f;
8920 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8921 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8922 rsurface.svector3f = rsurface.modelsvector3f;
8923 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8924 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8925 rsurface.tvector3f = rsurface.modeltvector3f;
8926 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8927 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8928 rsurface.normal3f = rsurface.modelnormal3f;
8929 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8930 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8931 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8933 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
8935 if ((wantnormals || wanttangents) && !normal3f)
8936 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8937 if (wanttangents && !svector3f)
8938 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);
8942 float RSurf_FogPoint(const float *v)
8944 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8945 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8946 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8947 float FogHeightFade = r_refdef.fogheightfade;
8949 unsigned int fogmasktableindex;
8950 if (r_refdef.fogplaneviewabove)
8951 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8953 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8954 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8955 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8958 float RSurf_FogVertex(const float *v)
8960 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8961 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8962 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8963 float FogHeightFade = rsurface.fogheightfade;
8965 unsigned int fogmasktableindex;
8966 if (r_refdef.fogplaneviewabove)
8967 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8969 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8970 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8971 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8974 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8975 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8978 int texturesurfaceindex;
8983 const float *v1, *in_tc;
8985 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8987 q3shaderinfo_deform_t *deform;
8988 // 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
8989 if (rsurface.generatedvertex)
8991 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
8992 generatenormals = true;
8993 for (i = 0;i < Q3MAXDEFORMS;i++)
8995 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
8997 generatetangents = true;
8998 generatenormals = true;
9000 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9001 generatenormals = true;
9003 if (generatenormals && !rsurface.modelnormal3f)
9005 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9006 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9007 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9008 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9010 if (generatetangents && !rsurface.modelsvector3f)
9012 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9013 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9014 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9015 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9016 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9017 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9018 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);
9021 rsurface.vertex3f = rsurface.modelvertex3f;
9022 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9023 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9024 rsurface.svector3f = rsurface.modelsvector3f;
9025 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9026 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9027 rsurface.tvector3f = rsurface.modeltvector3f;
9028 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9029 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9030 rsurface.normal3f = rsurface.modelnormal3f;
9031 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9032 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9033 // if vertices are deformed (sprite flares and things in maps, possibly
9034 // water waves, bulges and other deformations), generate them into
9035 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9036 // (may be static model data or generated data for an animated model, or
9037 // the previous deform pass)
9038 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9040 switch (deform->deform)
9043 case Q3DEFORM_PROJECTIONSHADOW:
9044 case Q3DEFORM_TEXT0:
9045 case Q3DEFORM_TEXT1:
9046 case Q3DEFORM_TEXT2:
9047 case Q3DEFORM_TEXT3:
9048 case Q3DEFORM_TEXT4:
9049 case Q3DEFORM_TEXT5:
9050 case Q3DEFORM_TEXT6:
9051 case Q3DEFORM_TEXT7:
9054 case Q3DEFORM_AUTOSPRITE:
9055 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9056 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9057 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9058 VectorNormalize(newforward);
9059 VectorNormalize(newright);
9060 VectorNormalize(newup);
9061 // make deformed versions of only the model vertices used by the specified surfaces
9062 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9064 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9065 // a single autosprite surface can contain multiple sprites...
9066 for (j = 0;j < surface->num_vertices - 3;j += 4)
9068 VectorClear(center);
9069 for (i = 0;i < 4;i++)
9070 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9071 VectorScale(center, 0.25f, center);
9072 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9073 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9074 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9075 for (i = 0;i < 4;i++)
9077 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9078 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9081 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);
9082 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);
9084 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9085 rsurface.vertex3f_bufferobject = 0;
9086 rsurface.vertex3f_bufferoffset = 0;
9087 rsurface.svector3f = rsurface.array_deformedsvector3f;
9088 rsurface.svector3f_bufferobject = 0;
9089 rsurface.svector3f_bufferoffset = 0;
9090 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9091 rsurface.tvector3f_bufferobject = 0;
9092 rsurface.tvector3f_bufferoffset = 0;
9093 rsurface.normal3f = rsurface.array_deformednormal3f;
9094 rsurface.normal3f_bufferobject = 0;
9095 rsurface.normal3f_bufferoffset = 0;
9097 case Q3DEFORM_AUTOSPRITE2:
9098 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9099 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9100 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9101 VectorNormalize(newforward);
9102 VectorNormalize(newright);
9103 VectorNormalize(newup);
9104 // make deformed versions of only the model vertices used by the specified surfaces
9105 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9107 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9108 const float *v1, *v2;
9118 memset(shortest, 0, sizeof(shortest));
9119 // a single autosprite surface can contain multiple sprites...
9120 for (j = 0;j < surface->num_vertices - 3;j += 4)
9122 VectorClear(center);
9123 for (i = 0;i < 4;i++)
9124 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9125 VectorScale(center, 0.25f, center);
9126 // find the two shortest edges, then use them to define the
9127 // axis vectors for rotating around the central axis
9128 for (i = 0;i < 6;i++)
9130 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9131 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9133 Debug_PolygonBegin(NULL, 0);
9134 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9135 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);
9136 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9139 l = VectorDistance2(v1, v2);
9140 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9142 l += (1.0f / 1024.0f);
9143 if (shortest[0].length2 > l || i == 0)
9145 shortest[1] = shortest[0];
9146 shortest[0].length2 = l;
9147 shortest[0].v1 = v1;
9148 shortest[0].v2 = v2;
9150 else if (shortest[1].length2 > l || i == 1)
9152 shortest[1].length2 = l;
9153 shortest[1].v1 = v1;
9154 shortest[1].v2 = v2;
9157 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9158 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9160 Debug_PolygonBegin(NULL, 0);
9161 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9162 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);
9163 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9166 // this calculates the right vector from the shortest edge
9167 // and the up vector from the edge midpoints
9168 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9169 VectorNormalize(right);
9170 VectorSubtract(end, start, up);
9171 VectorNormalize(up);
9172 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9173 VectorSubtract(rsurface.localvieworigin, center, forward);
9174 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9175 VectorNegate(forward, forward);
9176 VectorReflect(forward, 0, up, forward);
9177 VectorNormalize(forward);
9178 CrossProduct(up, forward, newright);
9179 VectorNormalize(newright);
9181 Debug_PolygonBegin(NULL, 0);
9182 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);
9183 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9184 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9188 Debug_PolygonBegin(NULL, 0);
9189 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9190 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9191 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9194 // rotate the quad around the up axis vector, this is made
9195 // especially easy by the fact we know the quad is flat,
9196 // so we only have to subtract the center position and
9197 // measure distance along the right vector, and then
9198 // multiply that by the newright vector and add back the
9200 // we also need to subtract the old position to undo the
9201 // displacement from the center, which we do with a
9202 // DotProduct, the subtraction/addition of center is also
9203 // optimized into DotProducts here
9204 l = DotProduct(right, center);
9205 for (i = 0;i < 4;i++)
9207 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9208 f = DotProduct(right, v1) - l;
9209 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9212 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);
9213 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);
9215 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9216 rsurface.vertex3f_bufferobject = 0;
9217 rsurface.vertex3f_bufferoffset = 0;
9218 rsurface.svector3f = rsurface.array_deformedsvector3f;
9219 rsurface.svector3f_bufferobject = 0;
9220 rsurface.svector3f_bufferoffset = 0;
9221 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9222 rsurface.tvector3f_bufferobject = 0;
9223 rsurface.tvector3f_bufferoffset = 0;
9224 rsurface.normal3f = rsurface.array_deformednormal3f;
9225 rsurface.normal3f_bufferobject = 0;
9226 rsurface.normal3f_bufferoffset = 0;
9228 case Q3DEFORM_NORMAL:
9229 // deform the normals to make reflections wavey
9230 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9232 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9233 for (j = 0;j < surface->num_vertices;j++)
9236 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9237 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9238 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9239 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9240 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9241 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9242 VectorNormalize(normal);
9244 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);
9246 rsurface.svector3f = rsurface.array_deformedsvector3f;
9247 rsurface.svector3f_bufferobject = 0;
9248 rsurface.svector3f_bufferoffset = 0;
9249 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9250 rsurface.tvector3f_bufferobject = 0;
9251 rsurface.tvector3f_bufferoffset = 0;
9252 rsurface.normal3f = rsurface.array_deformednormal3f;
9253 rsurface.normal3f_bufferobject = 0;
9254 rsurface.normal3f_bufferoffset = 0;
9257 // deform vertex array to make wavey water and flags and such
9258 waveparms[0] = deform->waveparms[0];
9259 waveparms[1] = deform->waveparms[1];
9260 waveparms[2] = deform->waveparms[2];
9261 waveparms[3] = deform->waveparms[3];
9262 // this is how a divisor of vertex influence on deformation
9263 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9264 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9265 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9267 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9268 for (j = 0;j < surface->num_vertices;j++)
9270 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
9271 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
9272 // if the wavefunc depends on time, evaluate it per-vertex
9275 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9276 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9278 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
9281 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9282 rsurface.vertex3f_bufferobject = 0;
9283 rsurface.vertex3f_bufferoffset = 0;
9285 case Q3DEFORM_BULGE:
9286 // deform vertex array to make the surface have moving bulges
9287 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9289 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9290 for (j = 0;j < surface->num_vertices;j++)
9292 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9293 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9296 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9297 rsurface.vertex3f_bufferobject = 0;
9298 rsurface.vertex3f_bufferoffset = 0;
9301 // deform vertex array
9302 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9303 VectorScale(deform->parms, scale, waveparms);
9304 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9306 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9307 for (j = 0;j < surface->num_vertices;j++)
9308 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9310 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9311 rsurface.vertex3f_bufferobject = 0;
9312 rsurface.vertex3f_bufferoffset = 0;
9316 // generate texcoords based on the chosen texcoord source
9317 switch(rsurface.texture->tcgen.tcgen)
9320 case Q3TCGEN_TEXTURE:
9321 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9322 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
9323 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9325 case Q3TCGEN_LIGHTMAP:
9326 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
9327 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9328 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9330 case Q3TCGEN_VECTOR:
9331 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9333 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9334 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)
9336 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9337 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9340 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9341 rsurface.texcoordtexture2f_bufferobject = 0;
9342 rsurface.texcoordtexture2f_bufferoffset = 0;
9344 case Q3TCGEN_ENVIRONMENT:
9345 // make environment reflections using a spheremap
9346 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9348 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9349 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9350 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9351 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9352 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9354 // identical to Q3A's method, but executed in worldspace so
9355 // carried models can be shiny too
9357 float viewer[3], d, reflected[3], worldreflected[3];
9359 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9360 // VectorNormalize(viewer);
9362 d = DotProduct(normal, viewer);
9364 reflected[0] = normal[0]*2*d - viewer[0];
9365 reflected[1] = normal[1]*2*d - viewer[1];
9366 reflected[2] = normal[2]*2*d - viewer[2];
9367 // note: this is proportinal to viewer, so we can normalize later
9369 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9370 VectorNormalize(worldreflected);
9372 // note: this sphere map only uses world x and z!
9373 // so positive and negative y will LOOK THE SAME.
9374 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9375 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9378 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9379 rsurface.texcoordtexture2f_bufferobject = 0;
9380 rsurface.texcoordtexture2f_bufferoffset = 0;
9383 // the only tcmod that needs software vertex processing is turbulent, so
9384 // check for it here and apply the changes if needed
9385 // and we only support that as the first one
9386 // (handling a mixture of turbulent and other tcmods would be problematic
9387 // without punting it entirely to a software path)
9388 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9390 amplitude = rsurface.texture->tcmods[0].parms[1];
9391 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9392 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9394 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9395 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)
9397 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9398 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9401 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9402 rsurface.texcoordtexture2f_bufferobject = 0;
9403 rsurface.texcoordtexture2f_bufferoffset = 0;
9405 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9406 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9407 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9408 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9411 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9414 const msurface_t *surface = texturesurfacelist[0];
9415 const msurface_t *surface2;
9420 // TODO: lock all array ranges before render, rather than on each surface
9421 if (texturenumsurfaces == 1)
9423 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9424 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);
9426 else if (r_batchmode.integer == 2)
9428 #define MAXBATCHTRIANGLES 4096
9429 int batchtriangles = 0;
9430 static int batchelements[MAXBATCHTRIANGLES*3];
9431 for (i = 0;i < texturenumsurfaces;i = j)
9433 surface = texturesurfacelist[i];
9435 if (surface->num_triangles > MAXBATCHTRIANGLES)
9437 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);
9440 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9441 batchtriangles = surface->num_triangles;
9442 firstvertex = surface->num_firstvertex;
9443 endvertex = surface->num_firstvertex + surface->num_vertices;
9444 for (;j < texturenumsurfaces;j++)
9446 surface2 = texturesurfacelist[j];
9447 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9449 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9450 batchtriangles += surface2->num_triangles;
9451 firstvertex = min(firstvertex, surface2->num_firstvertex);
9452 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9454 surface2 = texturesurfacelist[j-1];
9455 numvertices = endvertex - firstvertex;
9456 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9459 else if (r_batchmode.integer == 1)
9461 for (i = 0;i < texturenumsurfaces;i = j)
9463 surface = texturesurfacelist[i];
9464 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9465 if (texturesurfacelist[j] != surface2)
9467 surface2 = texturesurfacelist[j-1];
9468 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9469 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9470 GL_LockArrays(surface->num_firstvertex, numvertices);
9471 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9476 for (i = 0;i < texturenumsurfaces;i++)
9478 surface = texturesurfacelist[i];
9479 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9480 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);
9485 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9487 switch(vid.renderpath)
9489 case RENDERPATH_CGGL:
9491 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , R_GetTexture(surface->lightmaptexture ));CHECKCGERROR
9492 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, R_GetTexture(surface->deluxemaptexture));CHECKCGERROR
9495 case RENDERPATH_GL20:
9496 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(surface->lightmaptexture ));
9497 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, R_GetTexture(surface->deluxemaptexture));
9499 case RENDERPATH_GL13:
9500 case RENDERPATH_GL11:
9501 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
9506 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9508 // pick the closest matching water plane and bind textures
9509 int planeindex, vertexindex;
9513 r_waterstate_waterplane_t *p, *bestp;
9516 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9519 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9521 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9522 d += fabs(PlaneDiff(vert, &p->plane));
9524 if (bestd > d || !bestp)
9530 switch(vid.renderpath)
9532 case RENDERPATH_CGGL:
9534 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
9535 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
9538 case RENDERPATH_GL20:
9539 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));
9540 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));
9542 case RENDERPATH_GL13:
9543 case RENDERPATH_GL11:
9548 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9551 const msurface_t *surface;
9552 if (r_waterstate.renderingscene)
9554 for (i = 0;i < texturenumsurfaces;i++)
9556 surface = texturesurfacelist[i];
9557 RSurf_BindLightmapForSurface(surface);
9558 RSurf_BindReflectionForSurface(surface);
9559 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9560 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);
9564 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9568 const msurface_t *surface = texturesurfacelist[0];
9569 const msurface_t *surface2;
9574 if (texturenumsurfaces == 1)
9576 RSurf_BindLightmapForSurface(surface);
9577 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9578 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);
9580 else if (r_batchmode.integer == 2)
9582 #define MAXBATCHTRIANGLES 4096
9583 int batchtriangles = 0;
9584 static int batchelements[MAXBATCHTRIANGLES*3];
9585 for (i = 0;i < texturenumsurfaces;i = j)
9587 surface = texturesurfacelist[i];
9588 RSurf_BindLightmapForSurface(surface);
9590 if (surface->num_triangles > MAXBATCHTRIANGLES)
9592 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);
9595 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9596 batchtriangles = surface->num_triangles;
9597 firstvertex = surface->num_firstvertex;
9598 endvertex = surface->num_firstvertex + surface->num_vertices;
9599 for (;j < texturenumsurfaces;j++)
9601 surface2 = texturesurfacelist[j];
9602 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9604 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9605 batchtriangles += surface2->num_triangles;
9606 firstvertex = min(firstvertex, surface2->num_firstvertex);
9607 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9609 surface2 = texturesurfacelist[j-1];
9610 numvertices = endvertex - firstvertex;
9611 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9614 else if (r_batchmode.integer == 1)
9617 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9618 for (i = 0;i < texturenumsurfaces;i = j)
9620 surface = texturesurfacelist[i];
9621 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9622 if (texturesurfacelist[j] != surface2)
9624 Con_Printf(" %i", j - i);
9627 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9629 for (i = 0;i < texturenumsurfaces;i = j)
9631 surface = texturesurfacelist[i];
9632 RSurf_BindLightmapForSurface(surface);
9633 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9634 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9637 Con_Printf(" %i", j - i);
9639 surface2 = texturesurfacelist[j-1];
9640 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9641 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9642 GL_LockArrays(surface->num_firstvertex, numvertices);
9643 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9651 for (i = 0;i < texturenumsurfaces;i++)
9653 surface = texturesurfacelist[i];
9654 RSurf_BindLightmapForSurface(surface);
9655 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9656 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);
9661 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9664 int texturesurfaceindex;
9665 if (r_showsurfaces.integer == 2)
9667 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9669 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9670 for (j = 0;j < surface->num_triangles;j++)
9672 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9673 GL_Color(f, f, f, 1);
9674 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9680 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9682 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9683 int k = (int)(((size_t)surface) / sizeof(msurface_t));
9684 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);
9685 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9686 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);
9691 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9693 int texturesurfaceindex;
9697 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9699 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9700 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)
9708 rsurface.lightmapcolor4f = rsurface.array_color4f;
9709 rsurface.lightmapcolor4f_bufferobject = 0;
9710 rsurface.lightmapcolor4f_bufferoffset = 0;
9713 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9715 int texturesurfaceindex;
9721 if (rsurface.lightmapcolor4f)
9723 // generate color arrays for the surfaces in this list
9724 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9726 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9727 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)
9729 f = RSurf_FogVertex(v);
9739 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9741 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9742 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)
9744 f = RSurf_FogVertex(v);
9752 rsurface.lightmapcolor4f = rsurface.array_color4f;
9753 rsurface.lightmapcolor4f_bufferobject = 0;
9754 rsurface.lightmapcolor4f_bufferoffset = 0;
9757 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9759 int texturesurfaceindex;
9765 if (!rsurface.lightmapcolor4f)
9767 // generate color arrays for the surfaces in this list
9768 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9770 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9771 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)
9773 f = RSurf_FogVertex(v);
9774 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9775 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9776 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9780 rsurface.lightmapcolor4f = rsurface.array_color4f;
9781 rsurface.lightmapcolor4f_bufferobject = 0;
9782 rsurface.lightmapcolor4f_bufferoffset = 0;
9785 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
9787 int texturesurfaceindex;
9791 if (!rsurface.lightmapcolor4f)
9793 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9795 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9796 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)
9804 rsurface.lightmapcolor4f = rsurface.array_color4f;
9805 rsurface.lightmapcolor4f_bufferobject = 0;
9806 rsurface.lightmapcolor4f_bufferoffset = 0;
9809 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9811 int texturesurfaceindex;
9815 if (!rsurface.lightmapcolor4f)
9817 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9819 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9820 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)
9822 c2[0] = c[0] + r_refdef.scene.ambient;
9823 c2[1] = c[1] + r_refdef.scene.ambient;
9824 c2[2] = c[2] + r_refdef.scene.ambient;
9828 rsurface.lightmapcolor4f = rsurface.array_color4f;
9829 rsurface.lightmapcolor4f_bufferobject = 0;
9830 rsurface.lightmapcolor4f_bufferoffset = 0;
9833 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9836 rsurface.lightmapcolor4f = NULL;
9837 rsurface.lightmapcolor4f_bufferobject = 0;
9838 rsurface.lightmapcolor4f_bufferoffset = 0;
9839 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9840 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9841 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9842 GL_Color(r, g, b, a);
9843 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
9846 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9848 // TODO: optimize applyfog && applycolor case
9849 // just apply fog if necessary, and tint the fog color array if necessary
9850 rsurface.lightmapcolor4f = NULL;
9851 rsurface.lightmapcolor4f_bufferobject = 0;
9852 rsurface.lightmapcolor4f_bufferoffset = 0;
9853 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9854 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9855 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9856 GL_Color(r, g, b, a);
9857 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9860 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9862 int texturesurfaceindex;
9866 if (texturesurfacelist[0]->lightmapinfo)
9868 // generate color arrays for the surfaces in this list
9869 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9871 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9872 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
9874 if (surface->lightmapinfo->samples)
9876 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
9877 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
9878 VectorScale(lm, scale, c);
9879 if (surface->lightmapinfo->styles[1] != 255)
9881 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9883 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
9884 VectorMA(c, scale, lm, c);
9885 if (surface->lightmapinfo->styles[2] != 255)
9888 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
9889 VectorMA(c, scale, lm, c);
9890 if (surface->lightmapinfo->styles[3] != 255)
9893 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
9894 VectorMA(c, scale, lm, c);
9904 rsurface.lightmapcolor4f = rsurface.array_color4f;
9905 rsurface.lightmapcolor4f_bufferobject = 0;
9906 rsurface.lightmapcolor4f_bufferoffset = 0;
9910 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
9911 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
9912 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9914 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9915 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9916 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9917 GL_Color(r, g, b, a);
9918 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9921 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
9923 int texturesurfaceindex;
9930 vec3_t ambientcolor;
9931 vec3_t diffusecolor;
9935 VectorCopy(rsurface.modellight_lightdir, lightdir);
9936 f = 0.5f * r_refdef.lightmapintensity;
9937 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9938 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9939 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9940 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9941 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9942 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9944 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
9946 // generate color arrays for the surfaces in this list
9947 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9949 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9950 int numverts = surface->num_vertices;
9951 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
9952 n = rsurface.normal3f + 3 * surface->num_firstvertex;
9953 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
9954 // q3-style directional shading
9955 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
9957 if ((f = DotProduct(n, lightdir)) > 0)
9958 VectorMA(ambientcolor, f, diffusecolor, c);
9960 VectorCopy(ambientcolor, c);
9968 rsurface.lightmapcolor4f = rsurface.array_color4f;
9969 rsurface.lightmapcolor4f_bufferobject = 0;
9970 rsurface.lightmapcolor4f_bufferoffset = 0;
9971 *applycolor = false;
9975 *r = ambientcolor[0];
9976 *g = ambientcolor[1];
9977 *b = ambientcolor[2];
9978 rsurface.lightmapcolor4f = NULL;
9979 rsurface.lightmapcolor4f_bufferobject = 0;
9980 rsurface.lightmapcolor4f_bufferoffset = 0;
9984 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9986 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
9987 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9988 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9989 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9990 GL_Color(r, g, b, a);
9991 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9994 void RSurf_SetupDepthAndCulling(void)
9996 // submodels are biased to avoid z-fighting with world surfaces that they
9997 // may be exactly overlapping (avoids z-fighting artifacts on certain
9998 // doors and things in Quake maps)
9999 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10000 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10001 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10002 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10005 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10007 // transparent sky would be ridiculous
10008 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10010 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10011 skyrenderlater = true;
10012 RSurf_SetupDepthAndCulling();
10013 GL_DepthMask(true);
10014 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10015 // skymasking on them, and Quake3 never did sky masking (unlike
10016 // software Quake and software Quake2), so disable the sky masking
10017 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10018 // and skymasking also looks very bad when noclipping outside the
10019 // level, so don't use it then either.
10020 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10022 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10023 R_Mesh_ColorPointer(NULL, 0, 0);
10024 R_Mesh_ResetTextureState();
10025 if (skyrendermasked)
10027 R_SetupShader_DepthOrShadow();
10028 // depth-only (masking)
10029 GL_ColorMask(0,0,0,0);
10030 // just to make sure that braindead drivers don't draw
10031 // anything despite that colormask...
10032 GL_BlendFunc(GL_ZERO, GL_ONE);
10036 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10038 GL_BlendFunc(GL_ONE, GL_ZERO);
10040 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10041 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10042 if (skyrendermasked)
10043 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10045 R_Mesh_ResetTextureState();
10046 GL_Color(1, 1, 1, 1);
10049 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10050 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10051 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10053 qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
10054 qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
10056 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10059 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10060 R_Mesh_ColorPointer(NULL, 0, 0);
10062 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10066 // render background
10067 GL_BlendFunc(GL_ONE, GL_ZERO);
10068 GL_DepthMask(true);
10069 GL_AlphaTest(false);
10071 GL_Color(1, 1, 1, 1);
10072 R_Mesh_ColorPointer(NULL, 0, 0);
10074 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10075 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10076 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10077 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10078 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10079 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10080 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10081 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10082 GL_LockArrays(0, 0);
10084 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10085 GL_DepthMask(false);
10086 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10087 R_Mesh_ColorPointer(NULL, 0, 0);
10089 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10092 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10094 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10095 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10096 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10097 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10098 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10100 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10104 GL_BlendFunc(GL_ONE, GL_ZERO);
10105 GL_DepthMask(true);
10106 GL_AlphaTest(false);
10110 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10111 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10112 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
10115 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10117 if (refract || reflect)
10118 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10120 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10124 if (refract || reflect)
10125 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10127 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10129 GL_LockArrays(0, 0);
10132 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10134 // OpenGL 1.3 path - anything not completely ancient
10135 int texturesurfaceindex;
10136 qboolean applycolor;
10139 const texturelayer_t *layer;
10140 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10142 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10145 int layertexrgbscale;
10146 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10148 if (layerindex == 0)
10149 GL_AlphaTest(true);
10152 GL_AlphaTest(false);
10153 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10156 GL_DepthMask(layer->depthmask && writedepth);
10157 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10158 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10160 layertexrgbscale = 4;
10161 VectorScale(layer->color, 0.25f, layercolor);
10163 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10165 layertexrgbscale = 2;
10166 VectorScale(layer->color, 0.5f, layercolor);
10170 layertexrgbscale = 1;
10171 VectorScale(layer->color, 1.0f, layercolor);
10173 layercolor[3] = layer->color[3];
10174 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10175 R_Mesh_ColorPointer(NULL, 0, 0);
10176 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10177 switch (layer->type)
10179 case TEXTURELAYERTYPE_LITTEXTURE:
10180 // single-pass lightmapped texture with 2x rgbscale
10181 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
10182 R_Mesh_TexMatrix(0, NULL);
10183 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10184 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10185 R_Mesh_TexBind(1, R_GetTexture(layer->texture));
10186 R_Mesh_TexMatrix(1, &layer->texmatrix);
10187 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10188 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10189 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10190 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10191 else if (rsurface.uselightmaptexture)
10192 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10194 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10196 case TEXTURELAYERTYPE_TEXTURE:
10197 // singletexture unlit texture with transparency support
10198 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10199 R_Mesh_TexMatrix(0, &layer->texmatrix);
10200 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10201 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10202 R_Mesh_TexBind(1, 0);
10203 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10204 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10206 case TEXTURELAYERTYPE_FOG:
10207 // singletexture fogging
10208 if (layer->texture)
10210 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10211 R_Mesh_TexMatrix(0, &layer->texmatrix);
10212 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10213 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10217 R_Mesh_TexBind(0, 0);
10218 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10220 R_Mesh_TexBind(1, 0);
10221 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10222 // generate a color array for the fog pass
10223 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10224 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10230 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10231 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)
10233 f = 1 - RSurf_FogVertex(v);
10234 c[0] = layercolor[0];
10235 c[1] = layercolor[1];
10236 c[2] = layercolor[2];
10237 c[3] = f * layercolor[3];
10240 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10243 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10245 GL_LockArrays(0, 0);
10248 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10250 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10251 GL_AlphaTest(false);
10255 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10257 // OpenGL 1.1 - crusty old voodoo path
10258 int texturesurfaceindex;
10261 const texturelayer_t *layer;
10262 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10264 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10266 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10268 if (layerindex == 0)
10269 GL_AlphaTest(true);
10272 GL_AlphaTest(false);
10273 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10276 GL_DepthMask(layer->depthmask && writedepth);
10277 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10278 R_Mesh_ColorPointer(NULL, 0, 0);
10279 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10280 switch (layer->type)
10282 case TEXTURELAYERTYPE_LITTEXTURE:
10283 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10285 // two-pass lit texture with 2x rgbscale
10286 // first the lightmap pass
10287 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
10288 R_Mesh_TexMatrix(0, NULL);
10289 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10290 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10291 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10292 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10293 else if (rsurface.uselightmaptexture)
10294 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10296 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10297 GL_LockArrays(0, 0);
10298 // then apply the texture to it
10299 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10300 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10301 R_Mesh_TexMatrix(0, &layer->texmatrix);
10302 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10303 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10304 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);
10308 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10309 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10310 R_Mesh_TexMatrix(0, &layer->texmatrix);
10311 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10312 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10313 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10314 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);
10316 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);
10319 case TEXTURELAYERTYPE_TEXTURE:
10320 // singletexture unlit texture with transparency support
10321 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10322 R_Mesh_TexMatrix(0, &layer->texmatrix);
10323 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10324 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10325 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);
10327 case TEXTURELAYERTYPE_FOG:
10328 // singletexture fogging
10329 if (layer->texture)
10331 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10332 R_Mesh_TexMatrix(0, &layer->texmatrix);
10333 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10334 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10338 R_Mesh_TexBind(0, 0);
10339 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10341 // generate a color array for the fog pass
10342 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10343 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10349 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10350 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)
10352 f = 1 - RSurf_FogVertex(v);
10353 c[0] = layer->color[0];
10354 c[1] = layer->color[1];
10355 c[2] = layer->color[2];
10356 c[3] = f * layer->color[3];
10359 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10362 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10364 GL_LockArrays(0, 0);
10367 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10369 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10370 GL_AlphaTest(false);
10374 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10378 GL_AlphaTest(false);
10379 R_Mesh_ColorPointer(NULL, 0, 0);
10380 R_Mesh_ResetTextureState();
10381 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10383 if(rsurface.texture && rsurface.texture->currentskinframe)
10385 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10386 c[3] *= rsurface.texture->currentalpha;
10396 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10398 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10399 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10400 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10403 // brighten it up (as texture value 127 means "unlit")
10404 c[0] *= 2 * r_refdef.view.colorscale;
10405 c[1] *= 2 * r_refdef.view.colorscale;
10406 c[2] *= 2 * r_refdef.view.colorscale;
10408 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10409 c[3] *= r_wateralpha.value;
10411 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10413 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10414 GL_DepthMask(false);
10416 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10418 GL_BlendFunc(GL_ONE, GL_ONE);
10419 GL_DepthMask(false);
10421 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10423 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10424 GL_DepthMask(false);
10426 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10428 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10429 GL_DepthMask(false);
10433 GL_BlendFunc(GL_ONE, GL_ZERO);
10434 GL_DepthMask(writedepth);
10437 rsurface.lightmapcolor4f = NULL;
10439 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10441 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10443 rsurface.lightmapcolor4f = NULL;
10444 rsurface.lightmapcolor4f_bufferobject = 0;
10445 rsurface.lightmapcolor4f_bufferoffset = 0;
10447 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10449 qboolean applycolor = true;
10452 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10454 r_refdef.lightmapintensity = 1;
10455 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10456 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10460 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10462 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10463 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10464 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10467 if(!rsurface.lightmapcolor4f)
10468 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10470 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10471 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10472 if(r_refdef.fogenabled)
10473 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10475 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10476 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10479 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10482 RSurf_SetupDepthAndCulling();
10483 if (r_showsurfaces.integer == 3 && !prepass)
10485 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10488 switch (vid.renderpath)
10490 case RENDERPATH_GL20:
10491 case RENDERPATH_CGGL:
10492 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10494 case RENDERPATH_GL13:
10495 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10497 case RENDERPATH_GL11:
10498 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10504 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10507 RSurf_SetupDepthAndCulling();
10508 if (r_showsurfaces.integer == 3 && !prepass)
10510 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10513 switch (vid.renderpath)
10515 case RENDERPATH_GL20:
10516 case RENDERPATH_CGGL:
10517 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10519 case RENDERPATH_GL13:
10520 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10522 case RENDERPATH_GL11:
10523 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10529 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10532 int texturenumsurfaces, endsurface;
10533 texture_t *texture;
10534 const msurface_t *surface;
10535 const msurface_t *texturesurfacelist[256];
10537 // if the model is static it doesn't matter what value we give for
10538 // wantnormals and wanttangents, so this logic uses only rules applicable
10539 // to a model, knowing that they are meaningless otherwise
10540 if (ent == r_refdef.scene.worldentity)
10541 RSurf_ActiveWorldEntity();
10542 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10543 RSurf_ActiveModelEntity(ent, false, false, false);
10546 switch (vid.renderpath)
10548 case RENDERPATH_GL20:
10549 case RENDERPATH_CGGL:
10550 RSurf_ActiveModelEntity(ent, true, true, false);
10552 case RENDERPATH_GL13:
10553 case RENDERPATH_GL11:
10554 RSurf_ActiveModelEntity(ent, true, false, false);
10559 if (r_transparentdepthmasking.integer)
10561 qboolean setup = false;
10562 for (i = 0;i < numsurfaces;i = j)
10565 surface = rsurface.modelsurfaces + surfacelist[i];
10566 texture = surface->texture;
10567 rsurface.texture = R_GetCurrentTexture(texture);
10568 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10569 // scan ahead until we find a different texture
10570 endsurface = min(i + 1024, numsurfaces);
10571 texturenumsurfaces = 0;
10572 texturesurfacelist[texturenumsurfaces++] = surface;
10573 for (;j < endsurface;j++)
10575 surface = rsurface.modelsurfaces + surfacelist[j];
10576 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10578 texturesurfacelist[texturenumsurfaces++] = surface;
10580 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10582 // render the range of surfaces as depth
10586 GL_ColorMask(0,0,0,0);
10588 GL_DepthTest(true);
10589 GL_BlendFunc(GL_ONE, GL_ZERO);
10590 GL_DepthMask(true);
10591 GL_AlphaTest(false);
10592 R_Mesh_ColorPointer(NULL, 0, 0);
10593 R_Mesh_ResetTextureState();
10594 R_SetupShader_DepthOrShadow();
10596 RSurf_SetupDepthAndCulling();
10597 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10598 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10601 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10604 for (i = 0;i < numsurfaces;i = j)
10607 surface = rsurface.modelsurfaces + surfacelist[i];
10608 texture = surface->texture;
10609 rsurface.texture = R_GetCurrentTexture(texture);
10610 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10611 // scan ahead until we find a different texture
10612 endsurface = min(i + 1024, numsurfaces);
10613 texturenumsurfaces = 0;
10614 texturesurfacelist[texturenumsurfaces++] = surface;
10615 for (;j < endsurface;j++)
10617 surface = rsurface.modelsurfaces + surfacelist[j];
10618 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10620 texturesurfacelist[texturenumsurfaces++] = surface;
10622 // render the range of surfaces
10623 if (ent == r_refdef.scene.worldentity)
10624 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10626 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10628 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10629 GL_AlphaTest(false);
10632 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10634 // transparent surfaces get pushed off into the transparent queue
10635 int surfacelistindex;
10636 const msurface_t *surface;
10637 vec3_t tempcenter, center;
10638 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10640 surface = texturesurfacelist[surfacelistindex];
10641 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10642 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10643 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10644 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10645 if (queueentity->transparent_offset) // transparent offset
10647 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10648 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10649 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10651 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10655 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10657 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10661 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10663 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10665 RSurf_SetupDepthAndCulling();
10666 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10667 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10671 if (!rsurface.texture->currentnumlayers)
10673 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10674 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10676 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10678 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10680 RSurf_SetupDepthAndCulling();
10681 GL_AlphaTest(false);
10682 R_Mesh_ColorPointer(NULL, 0, 0);
10683 R_Mesh_ResetTextureState();
10684 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10685 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10686 GL_DepthMask(true);
10687 GL_BlendFunc(GL_ONE, GL_ZERO);
10688 GL_Color(0, 0, 0, 1);
10689 GL_DepthTest(writedepth);
10690 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10692 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10694 RSurf_SetupDepthAndCulling();
10695 GL_AlphaTest(false);
10696 R_Mesh_ColorPointer(NULL, 0, 0);
10697 R_Mesh_ResetTextureState();
10698 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10699 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10700 GL_DepthMask(true);
10701 GL_BlendFunc(GL_ONE, GL_ZERO);
10702 GL_DepthTest(true);
10703 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10705 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10706 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10707 else if (!rsurface.texture->currentnumlayers)
10709 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10711 // in the deferred case, transparent surfaces were queued during prepass
10712 if (!r_shadow_usingdeferredprepass)
10713 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10717 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10718 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10723 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10726 texture_t *texture;
10727 // break the surface list down into batches by texture and use of lightmapping
10728 for (i = 0;i < numsurfaces;i = j)
10731 // texture is the base texture pointer, rsurface.texture is the
10732 // current frame/skin the texture is directing us to use (for example
10733 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10734 // use skin 1 instead)
10735 texture = surfacelist[i]->texture;
10736 rsurface.texture = R_GetCurrentTexture(texture);
10737 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10738 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10740 // if this texture is not the kind we want, skip ahead to the next one
10741 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10745 // simply scan ahead until we find a different texture or lightmap state
10746 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10748 // render the range of surfaces
10749 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10753 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10758 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10760 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10762 RSurf_SetupDepthAndCulling();
10763 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10764 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10768 if (!rsurface.texture->currentnumlayers)
10770 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10771 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10773 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10775 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10777 RSurf_SetupDepthAndCulling();
10778 GL_AlphaTest(false);
10779 R_Mesh_ColorPointer(NULL, 0, 0);
10780 R_Mesh_ResetTextureState();
10781 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10782 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10783 GL_DepthMask(true);
10784 GL_BlendFunc(GL_ONE, GL_ZERO);
10785 GL_Color(0, 0, 0, 1);
10786 GL_DepthTest(writedepth);
10787 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10789 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10791 RSurf_SetupDepthAndCulling();
10792 GL_AlphaTest(false);
10793 R_Mesh_ColorPointer(NULL, 0, 0);
10794 R_Mesh_ResetTextureState();
10795 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10796 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10797 GL_DepthMask(true);
10798 GL_BlendFunc(GL_ONE, GL_ZERO);
10799 GL_DepthTest(true);
10800 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10802 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10803 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10804 else if (!rsurface.texture->currentnumlayers)
10806 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10808 // in the deferred case, transparent surfaces were queued during prepass
10809 if (!r_shadow_usingdeferredprepass)
10810 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10814 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10815 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10820 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10823 texture_t *texture;
10824 // break the surface list down into batches by texture and use of lightmapping
10825 for (i = 0;i < numsurfaces;i = j)
10828 // texture is the base texture pointer, rsurface.texture is the
10829 // current frame/skin the texture is directing us to use (for example
10830 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10831 // use skin 1 instead)
10832 texture = surfacelist[i]->texture;
10833 rsurface.texture = R_GetCurrentTexture(texture);
10834 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10835 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10837 // if this texture is not the kind we want, skip ahead to the next one
10838 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10842 // simply scan ahead until we find a different texture or lightmap state
10843 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10845 // render the range of surfaces
10846 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10850 float locboxvertex3f[6*4*3] =
10852 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10853 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10854 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10855 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10856 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10857 1,0,0, 0,0,0, 0,1,0, 1,1,0
10860 unsigned short locboxelements[6*2*3] =
10865 12,13,14, 12,14,15,
10866 16,17,18, 16,18,19,
10870 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10873 cl_locnode_t *loc = (cl_locnode_t *)ent;
10875 float vertex3f[6*4*3];
10877 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10878 GL_DepthMask(false);
10879 GL_DepthRange(0, 1);
10880 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10881 GL_DepthTest(true);
10882 GL_CullFace(GL_NONE);
10883 R_EntityMatrix(&identitymatrix);
10885 R_Mesh_VertexPointer(vertex3f, 0, 0);
10886 R_Mesh_ColorPointer(NULL, 0, 0);
10887 R_Mesh_ResetTextureState();
10888 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10890 i = surfacelist[0];
10891 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10892 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10893 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10894 surfacelist[0] < 0 ? 0.5f : 0.125f);
10896 if (VectorCompare(loc->mins, loc->maxs))
10898 VectorSet(size, 2, 2, 2);
10899 VectorMA(loc->mins, -0.5f, size, mins);
10903 VectorCopy(loc->mins, mins);
10904 VectorSubtract(loc->maxs, loc->mins, size);
10907 for (i = 0;i < 6*4*3;)
10908 for (j = 0;j < 3;j++, i++)
10909 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10911 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
10914 void R_DrawLocs(void)
10917 cl_locnode_t *loc, *nearestloc;
10919 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10920 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10922 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10923 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10927 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10929 if (decalsystem->decals)
10930 Mem_Free(decalsystem->decals);
10931 memset(decalsystem, 0, sizeof(*decalsystem));
10934 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)
10937 tridecal_t *decals;
10941 // expand or initialize the system
10942 if (decalsystem->maxdecals <= decalsystem->numdecals)
10944 decalsystem_t old = *decalsystem;
10945 qboolean useshortelements;
10946 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10947 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10948 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)));
10949 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10950 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10951 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10952 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10953 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10954 if (decalsystem->numdecals)
10955 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10957 Mem_Free(old.decals);
10958 for (i = 0;i < decalsystem->maxdecals*3;i++)
10959 decalsystem->element3i[i] = i;
10960 if (useshortelements)
10961 for (i = 0;i < decalsystem->maxdecals*3;i++)
10962 decalsystem->element3s[i] = i;
10965 // grab a decal and search for another free slot for the next one
10966 maxdecals = decalsystem->maxdecals;
10967 decals = decalsystem->decals;
10968 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10969 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
10971 decalsystem->freedecal = i;
10972 if (decalsystem->numdecals <= i)
10973 decalsystem->numdecals = i + 1;
10975 // initialize the decal
10977 decal->triangleindex = triangleindex;
10978 decal->surfaceindex = surfaceindex;
10979 decal->decalsequence = decalsequence;
10980 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
10981 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
10982 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
10983 decal->color4ub[0][3] = 255;
10984 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
10985 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
10986 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
10987 decal->color4ub[1][3] = 255;
10988 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
10989 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
10990 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
10991 decal->color4ub[2][3] = 255;
10992 decal->vertex3f[0][0] = v0[0];
10993 decal->vertex3f[0][1] = v0[1];
10994 decal->vertex3f[0][2] = v0[2];
10995 decal->vertex3f[1][0] = v1[0];
10996 decal->vertex3f[1][1] = v1[1];
10997 decal->vertex3f[1][2] = v1[2];
10998 decal->vertex3f[2][0] = v2[0];
10999 decal->vertex3f[2][1] = v2[1];
11000 decal->vertex3f[2][2] = v2[2];
11001 decal->texcoord2f[0][0] = t0[0];
11002 decal->texcoord2f[0][1] = t0[1];
11003 decal->texcoord2f[1][0] = t1[0];
11004 decal->texcoord2f[1][1] = t1[1];
11005 decal->texcoord2f[2][0] = t2[0];
11006 decal->texcoord2f[2][1] = t2[1];
11009 extern cvar_t cl_decals_bias;
11010 extern cvar_t cl_decals_models;
11011 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11012 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)
11014 matrix4x4_t projection;
11015 decalsystem_t *decalsystem;
11018 const float *vertex3f;
11019 const msurface_t *surface;
11020 const msurface_t *surfaces;
11021 const int *surfacelist;
11022 const texture_t *texture;
11025 int numsurfacelist;
11026 int surfacelistindex;
11029 int decalsurfaceindex;
11034 float localorigin[3];
11035 float localnormal[3];
11036 float localmins[3];
11037 float localmaxs[3];
11044 float planes[6][4];
11046 float points[2][9][3];
11050 decalsystem = &ent->decalsystem;
11051 model = ent->model;
11052 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11054 R_DecalSystem_Reset(&ent->decalsystem);
11058 if (!model->brush.data_nodes && !cl_decals_models.integer)
11060 if (decalsystem->model)
11061 R_DecalSystem_Reset(decalsystem);
11065 if (decalsystem->model != model)
11066 R_DecalSystem_Reset(decalsystem);
11067 decalsystem->model = model;
11069 RSurf_ActiveModelEntity(ent, false, false, false);
11071 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11072 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11073 VectorNormalize(localnormal);
11074 localsize = worldsize*rsurface.inversematrixscale;
11075 ilocalsize = 1.0f / localsize;
11076 localmins[0] = localorigin[0] - localsize;
11077 localmins[1] = localorigin[1] - localsize;
11078 localmins[2] = localorigin[2] - localsize;
11079 localmaxs[0] = localorigin[0] + localsize;
11080 localmaxs[1] = localorigin[1] + localsize;
11081 localmaxs[2] = localorigin[2] + localsize;
11083 //VectorCopy(localnormal, planes[4]);
11084 //VectorVectors(planes[4], planes[2], planes[0]);
11085 AnglesFromVectors(angles, localnormal, NULL, false);
11086 AngleVectors(angles, planes[0], planes[2], planes[4]);
11087 VectorNegate(planes[0], planes[1]);
11088 VectorNegate(planes[2], planes[3]);
11089 VectorNegate(planes[4], planes[5]);
11090 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11091 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11092 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11093 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11094 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11095 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11100 matrix4x4_t forwardprojection;
11101 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11102 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11107 float projectionvector[4][3];
11108 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11109 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11110 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11111 projectionvector[0][0] = planes[0][0] * ilocalsize;
11112 projectionvector[0][1] = planes[1][0] * ilocalsize;
11113 projectionvector[0][2] = planes[2][0] * ilocalsize;
11114 projectionvector[1][0] = planes[0][1] * ilocalsize;
11115 projectionvector[1][1] = planes[1][1] * ilocalsize;
11116 projectionvector[1][2] = planes[2][1] * ilocalsize;
11117 projectionvector[2][0] = planes[0][2] * ilocalsize;
11118 projectionvector[2][1] = planes[1][2] * ilocalsize;
11119 projectionvector[2][2] = planes[2][2] * ilocalsize;
11120 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11121 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11122 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11123 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11127 dynamic = model->surfmesh.isanimated;
11128 vertex3f = rsurface.modelvertex3f;
11129 numsurfacelist = model->nummodelsurfaces;
11130 surfacelist = model->sortedmodelsurfaces;
11131 surfaces = model->data_surfaces;
11132 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11134 surfaceindex = surfacelist[surfacelistindex];
11135 surface = surfaces + surfaceindex;
11136 // skip transparent surfaces
11137 texture = surface->texture;
11138 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11140 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11142 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11144 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11145 numvertices = surface->num_vertices;
11146 numtriangles = surface->num_triangles;
11147 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11149 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11151 index = 3*e[cornerindex];
11152 VectorCopy(vertex3f + index, v[cornerindex]);
11155 //TriangleNormal(v[0], v[1], v[2], normal);
11156 //if (DotProduct(normal, localnormal) < 0.0f)
11158 // clip by each of the box planes formed from the projection matrix
11159 // if anything survives, we emit the decal
11160 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]);
11163 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]);
11166 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]);
11169 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]);
11172 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]);
11175 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]);
11178 // some part of the triangle survived, so we have to accept it...
11181 // dynamic always uses the original triangle
11183 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11185 index = 3*e[cornerindex];
11186 VectorCopy(vertex3f + index, v[cornerindex]);
11189 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11191 // convert vertex positions to texcoords
11192 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11193 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11194 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11195 // calculate distance fade from the projection origin
11196 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11197 f = bound(0.0f, f, 1.0f);
11198 c[cornerindex][0] = r * f;
11199 c[cornerindex][1] = g * f;
11200 c[cornerindex][2] = b * f;
11201 c[cornerindex][3] = 1.0f;
11202 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11205 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);
11207 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11208 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);
11213 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11214 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)
11216 int renderentityindex;
11217 float worldmins[3];
11218 float worldmaxs[3];
11219 entity_render_t *ent;
11221 if (!cl_decals_newsystem.integer)
11224 worldmins[0] = worldorigin[0] - worldsize;
11225 worldmins[1] = worldorigin[1] - worldsize;
11226 worldmins[2] = worldorigin[2] - worldsize;
11227 worldmaxs[0] = worldorigin[0] + worldsize;
11228 worldmaxs[1] = worldorigin[1] + worldsize;
11229 worldmaxs[2] = worldorigin[2] + worldsize;
11231 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11233 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11235 ent = r_refdef.scene.entities[renderentityindex];
11236 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11239 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11243 typedef struct r_decalsystem_splatqueue_s
11245 vec3_t worldorigin;
11246 vec3_t worldnormal;
11252 r_decalsystem_splatqueue_t;
11254 int r_decalsystem_numqueued = 0;
11255 #define MAX_DECALSYSTEM_QUEUE 1024
11256 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11258 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)
11260 r_decalsystem_splatqueue_t *queue;
11262 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11265 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11266 VectorCopy(worldorigin, queue->worldorigin);
11267 VectorCopy(worldnormal, queue->worldnormal);
11268 Vector4Set(queue->color, r, g, b, a);
11269 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11270 queue->worldsize = worldsize;
11271 queue->decalsequence = cl.decalsequence++;
11274 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11277 r_decalsystem_splatqueue_t *queue;
11279 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11280 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);
11281 r_decalsystem_numqueued = 0;
11284 extern cvar_t cl_decals_max;
11285 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11288 decalsystem_t *decalsystem = &ent->decalsystem;
11295 if (!decalsystem->numdecals)
11298 if (r_showsurfaces.integer)
11301 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11303 R_DecalSystem_Reset(decalsystem);
11307 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11308 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11310 if (decalsystem->lastupdatetime)
11311 frametime = (cl.time - decalsystem->lastupdatetime);
11314 decalsystem->lastupdatetime = cl.time;
11315 decal = decalsystem->decals;
11316 numdecals = decalsystem->numdecals;
11318 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11320 if (decal->color4ub[0][3])
11322 decal->lived += frametime;
11323 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11325 memset(decal, 0, sizeof(*decal));
11326 if (decalsystem->freedecal > i)
11327 decalsystem->freedecal = i;
11331 decal = decalsystem->decals;
11332 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11335 // collapse the array by shuffling the tail decals into the gaps
11338 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11339 decalsystem->freedecal++;
11340 if (decalsystem->freedecal == numdecals)
11342 decal[decalsystem->freedecal] = decal[--numdecals];
11345 decalsystem->numdecals = numdecals;
11347 if (numdecals <= 0)
11349 // if there are no decals left, reset decalsystem
11350 R_DecalSystem_Reset(decalsystem);
11354 extern skinframe_t *decalskinframe;
11355 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11358 decalsystem_t *decalsystem = &ent->decalsystem;
11368 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11371 numdecals = decalsystem->numdecals;
11375 if (r_showsurfaces.integer)
11378 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11380 R_DecalSystem_Reset(decalsystem);
11384 // if the model is static it doesn't matter what value we give for
11385 // wantnormals and wanttangents, so this logic uses only rules applicable
11386 // to a model, knowing that they are meaningless otherwise
11387 if (ent == r_refdef.scene.worldentity)
11388 RSurf_ActiveWorldEntity();
11390 RSurf_ActiveModelEntity(ent, false, false, false);
11392 decalsystem->lastupdatetime = cl.time;
11393 decal = decalsystem->decals;
11395 fadedelay = cl_decals_time.value;
11396 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11398 // update vertex positions for animated models
11399 v3f = decalsystem->vertex3f;
11400 c4f = decalsystem->color4f;
11401 t2f = decalsystem->texcoord2f;
11402 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11404 if (!decal->color4ub[0][3])
11407 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11410 // update color values for fading decals
11411 if (decal->lived >= cl_decals_time.value)
11413 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11414 alpha *= (1.0f/255.0f);
11417 alpha = 1.0f/255.0f;
11419 c4f[ 0] = decal->color4ub[0][0] * alpha;
11420 c4f[ 1] = decal->color4ub[0][1] * alpha;
11421 c4f[ 2] = decal->color4ub[0][2] * alpha;
11423 c4f[ 4] = decal->color4ub[1][0] * alpha;
11424 c4f[ 5] = decal->color4ub[1][1] * alpha;
11425 c4f[ 6] = decal->color4ub[1][2] * alpha;
11427 c4f[ 8] = decal->color4ub[2][0] * alpha;
11428 c4f[ 9] = decal->color4ub[2][1] * alpha;
11429 c4f[10] = decal->color4ub[2][2] * alpha;
11432 t2f[0] = decal->texcoord2f[0][0];
11433 t2f[1] = decal->texcoord2f[0][1];
11434 t2f[2] = decal->texcoord2f[1][0];
11435 t2f[3] = decal->texcoord2f[1][1];
11436 t2f[4] = decal->texcoord2f[2][0];
11437 t2f[5] = decal->texcoord2f[2][1];
11439 // update vertex positions for animated models
11440 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11442 e = rsurface.modelelement3i + 3*decal->triangleindex;
11443 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11444 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11445 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11449 VectorCopy(decal->vertex3f[0], v3f);
11450 VectorCopy(decal->vertex3f[1], v3f + 3);
11451 VectorCopy(decal->vertex3f[2], v3f + 6);
11462 r_refdef.stats.drawndecals += numtris;
11464 if (r_refdef.fogenabled)
11466 switch(vid.renderpath)
11468 case RENDERPATH_GL20:
11469 case RENDERPATH_CGGL:
11470 case RENDERPATH_GL13:
11471 case RENDERPATH_GL11:
11472 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11474 alpha = RSurf_FogVertex(v3f);
11483 // now render the decals all at once
11484 // (this assumes they all use one particle font texture!)
11485 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);
11486 R_Mesh_ResetTextureState();
11487 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11488 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11489 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11490 GL_DepthMask(false);
11491 GL_DepthRange(0, 1);
11492 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11493 GL_DepthTest(true);
11494 GL_CullFace(GL_NONE);
11495 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11496 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11497 GL_LockArrays(0, numtris * 3);
11498 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11499 GL_LockArrays(0, 0);
11503 static void R_DrawModelDecals(void)
11507 // fade faster when there are too many decals
11508 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11509 for (i = 0;i < r_refdef.scene.numentities;i++)
11510 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11512 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11513 for (i = 0;i < r_refdef.scene.numentities;i++)
11514 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11515 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11517 R_DecalSystem_ApplySplatEntitiesQueue();
11519 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11520 for (i = 0;i < r_refdef.scene.numentities;i++)
11521 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11523 r_refdef.stats.totaldecals += numdecals;
11525 if (r_showsurfaces.integer)
11528 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11530 for (i = 0;i < r_refdef.scene.numentities;i++)
11532 if (!r_refdef.viewcache.entityvisible[i])
11534 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11535 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11539 void R_DrawDebugModel(void)
11541 entity_render_t *ent = rsurface.entity;
11542 int i, j, k, l, flagsmask;
11543 const int *elements;
11545 const msurface_t *surface;
11546 dp_model_t *model = ent->model;
11549 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11551 R_Mesh_ColorPointer(NULL, 0, 0);
11552 R_Mesh_ResetTextureState();
11553 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11554 GL_DepthRange(0, 1);
11555 GL_DepthTest(!r_showdisabledepthtest.integer);
11556 GL_DepthMask(false);
11557 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11559 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11561 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11562 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11564 if (brush->colbrushf && brush->colbrushf->numtriangles)
11566 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11567 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);
11568 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11571 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11573 if (surface->num_collisiontriangles)
11575 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11576 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);
11577 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11582 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11584 if (r_showtris.integer || r_shownormals.integer)
11586 if (r_showdisabledepthtest.integer)
11588 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11589 GL_DepthMask(false);
11593 GL_BlendFunc(GL_ONE, GL_ZERO);
11594 GL_DepthMask(true);
11596 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11598 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11600 rsurface.texture = R_GetCurrentTexture(surface->texture);
11601 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11603 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11604 if (r_showtris.value > 0)
11606 if (!rsurface.texture->currentlayers->depthmask)
11607 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11608 else if (ent == r_refdef.scene.worldentity)
11609 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11611 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11612 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11613 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11614 R_Mesh_ColorPointer(NULL, 0, 0);
11615 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11616 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11617 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11618 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);
11619 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11622 if (r_shownormals.value < 0)
11624 qglBegin(GL_LINES);
11625 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11627 VectorCopy(rsurface.vertex3f + l * 3, v);
11628 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11629 qglVertex3f(v[0], v[1], v[2]);
11630 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11631 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11632 qglVertex3f(v[0], v[1], v[2]);
11637 if (r_shownormals.value > 0)
11639 qglBegin(GL_LINES);
11640 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11642 VectorCopy(rsurface.vertex3f + l * 3, v);
11643 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11644 qglVertex3f(v[0], v[1], v[2]);
11645 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11646 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11647 qglVertex3f(v[0], v[1], v[2]);
11651 qglBegin(GL_LINES);
11652 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11654 VectorCopy(rsurface.vertex3f + l * 3, v);
11655 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11656 qglVertex3f(v[0], v[1], v[2]);
11657 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11658 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11659 qglVertex3f(v[0], v[1], v[2]);
11663 qglBegin(GL_LINES);
11664 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11666 VectorCopy(rsurface.vertex3f + l * 3, v);
11667 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11668 qglVertex3f(v[0], v[1], v[2]);
11669 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11670 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11671 qglVertex3f(v[0], v[1], v[2]);
11678 rsurface.texture = NULL;
11682 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11683 int r_maxsurfacelist = 0;
11684 const msurface_t **r_surfacelist = NULL;
11685 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11687 int i, j, endj, f, flagsmask;
11689 dp_model_t *model = r_refdef.scene.worldmodel;
11690 msurface_t *surfaces;
11691 unsigned char *update;
11692 int numsurfacelist = 0;
11696 if (r_maxsurfacelist < model->num_surfaces)
11698 r_maxsurfacelist = model->num_surfaces;
11700 Mem_Free((msurface_t**)r_surfacelist);
11701 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11704 RSurf_ActiveWorldEntity();
11706 surfaces = model->data_surfaces;
11707 update = model->brushq1.lightmapupdateflags;
11709 // update light styles on this submodel
11710 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11712 model_brush_lightstyleinfo_t *style;
11713 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11715 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11717 int *list = style->surfacelist;
11718 style->value = r_refdef.scene.lightstylevalue[style->style];
11719 for (j = 0;j < style->numsurfaces;j++)
11720 update[list[j]] = true;
11725 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11729 R_DrawDebugModel();
11730 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11736 rsurface.uselightmaptexture = false;
11737 rsurface.texture = NULL;
11738 rsurface.rtlight = NULL;
11739 numsurfacelist = 0;
11740 // add visible surfaces to draw list
11741 for (i = 0;i < model->nummodelsurfaces;i++)
11743 j = model->sortedmodelsurfaces[i];
11744 if (r_refdef.viewcache.world_surfacevisible[j])
11745 r_surfacelist[numsurfacelist++] = surfaces + j;
11747 // update lightmaps if needed
11751 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11753 if (r_refdef.viewcache.world_surfacevisible[j])
11758 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11764 int count = model->brushq3.num_mergedlightmaps;
11765 for (i = 0;i < count;i++)
11767 if (model->brushq3.data_deluxemaps[i])
11768 R_FlushTexture(model->brushq3.data_deluxemaps[i]);
11769 if (model->brushq3.data_lightmaps[i])
11770 R_FlushTexture(model->brushq3.data_lightmaps[i]);
11774 // don't do anything if there were no surfaces
11775 if (!numsurfacelist)
11777 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11780 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11781 GL_AlphaTest(false);
11783 // add to stats if desired
11784 if (r_speeds.integer && !skysurfaces && !depthonly)
11786 r_refdef.stats.world_surfaces += numsurfacelist;
11787 for (j = 0;j < numsurfacelist;j++)
11788 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11791 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11794 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11796 int i, j, endj, f, flagsmask;
11798 dp_model_t *model = ent->model;
11799 msurface_t *surfaces;
11800 unsigned char *update;
11801 int numsurfacelist = 0;
11805 if (r_maxsurfacelist < model->num_surfaces)
11807 r_maxsurfacelist = model->num_surfaces;
11809 Mem_Free((msurface_t **)r_surfacelist);
11810 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11813 // if the model is static it doesn't matter what value we give for
11814 // wantnormals and wanttangents, so this logic uses only rules applicable
11815 // to a model, knowing that they are meaningless otherwise
11816 if (ent == r_refdef.scene.worldentity)
11817 RSurf_ActiveWorldEntity();
11818 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11819 RSurf_ActiveModelEntity(ent, false, false, false);
11821 RSurf_ActiveModelEntity(ent, true, true, true);
11822 else if (depthonly)
11823 RSurf_ActiveModelEntity(ent, false, false, false);
11826 switch (vid.renderpath)
11828 case RENDERPATH_GL20:
11829 case RENDERPATH_CGGL:
11830 RSurf_ActiveModelEntity(ent, true, true, false);
11832 case RENDERPATH_GL13:
11833 case RENDERPATH_GL11:
11834 RSurf_ActiveModelEntity(ent, true, false, false);
11839 surfaces = model->data_surfaces;
11840 update = model->brushq1.lightmapupdateflags;
11842 // update light styles
11843 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11845 model_brush_lightstyleinfo_t *style;
11846 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11848 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11850 int *list = style->surfacelist;
11851 style->value = r_refdef.scene.lightstylevalue[style->style];
11852 for (j = 0;j < style->numsurfaces;j++)
11853 update[list[j]] = true;
11858 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11862 R_DrawDebugModel();
11863 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11869 rsurface.uselightmaptexture = false;
11870 rsurface.texture = NULL;
11871 rsurface.rtlight = NULL;
11872 numsurfacelist = 0;
11873 // add visible surfaces to draw list
11874 for (i = 0;i < model->nummodelsurfaces;i++)
11875 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11876 // don't do anything if there were no surfaces
11877 if (!numsurfacelist)
11879 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11882 // update lightmaps if needed
11886 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11891 R_BuildLightMap(ent, surfaces + j);
11896 int count = model->brushq3.num_mergedlightmaps;
11897 for (i = 0;i < count;i++)
11899 if (model->brushq3.data_deluxemaps[i])
11900 R_FlushTexture(model->brushq3.data_deluxemaps[i]);
11901 if (model->brushq3.data_lightmaps[i])
11902 R_FlushTexture(model->brushq3.data_lightmaps[i]);
11907 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11909 R_BuildLightMap(ent, surfaces + j);
11910 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11911 GL_AlphaTest(false);
11913 // add to stats if desired
11914 if (r_speeds.integer && !skysurfaces && !depthonly)
11916 r_refdef.stats.entities_surfaces += numsurfacelist;
11917 for (j = 0;j < numsurfacelist;j++)
11918 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11921 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11924 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11926 static texture_t texture;
11927 static msurface_t surface;
11928 const msurface_t *surfacelist = &surface;
11930 // fake enough texture and surface state to render this geometry
11932 texture.update_lastrenderframe = -1; // regenerate this texture
11933 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11934 texture.currentskinframe = skinframe;
11935 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11936 texture.specularscalemod = 1;
11937 texture.specularpowermod = 1;
11939 surface.texture = &texture;
11940 surface.num_triangles = numtriangles;
11941 surface.num_firsttriangle = firsttriangle;
11942 surface.num_vertices = numvertices;
11943 surface.num_firstvertex = firstvertex;
11946 rsurface.texture = R_GetCurrentTexture(surface.texture);
11947 rsurface.uselightmaptexture = false;
11948 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11951 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)
11953 static msurface_t surface;
11954 const msurface_t *surfacelist = &surface;
11956 // fake enough texture and surface state to render this geometry
11958 surface.texture = texture;
11959 surface.num_triangles = numtriangles;
11960 surface.num_firsttriangle = firsttriangle;
11961 surface.num_vertices = numvertices;
11962 surface.num_firstvertex = firstvertex;
11965 rsurface.texture = R_GetCurrentTexture(surface.texture);
11966 rsurface.uselightmaptexture = false;
11967 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);