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 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 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)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 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"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 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)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
60 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"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
66 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)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 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"};
70 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"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 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"};
73 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"};
74 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"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 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)"};
80 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)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 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."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 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."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 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"};
96 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"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 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"};
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
112 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
113 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
115 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
116 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
117 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
119 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)"};
120 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
121 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
122 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
123 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
124 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)"};
125 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)"};
126 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)"};
127 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)"};
129 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)"};
130 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
131 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"};
132 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
133 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
135 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
136 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
137 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
138 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
140 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
141 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
142 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
143 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
144 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
145 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
146 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
148 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
149 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
150 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
151 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)"};
153 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"};
155 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"};
157 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
159 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
160 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
161 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"};
162 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
163 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
164 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
165 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
167 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)"};
169 extern cvar_t v_glslgamma;
171 extern qboolean v_flipped_state;
173 static struct r_bloomstate_s
178 int bloomwidth, bloomheight;
180 int screentexturewidth, screentextureheight;
181 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
183 int bloomtexturewidth, bloomtextureheight;
184 rtexture_t *texture_bloom;
186 // arrays for rendering the screen passes
187 float screentexcoord2f[8];
188 float bloomtexcoord2f[8];
189 float offsettexcoord2f[8];
191 r_viewport_t viewport;
195 r_waterstate_t r_waterstate;
197 /// shadow volume bsp struct with automatically growing nodes buffer
200 rtexture_t *r_texture_blanknormalmap;
201 rtexture_t *r_texture_white;
202 rtexture_t *r_texture_grey128;
203 rtexture_t *r_texture_black;
204 rtexture_t *r_texture_notexture;
205 rtexture_t *r_texture_whitecube;
206 rtexture_t *r_texture_normalizationcube;
207 rtexture_t *r_texture_fogattenuation;
208 rtexture_t *r_texture_gammaramps;
209 unsigned int r_texture_gammaramps_serial;
210 //rtexture_t *r_texture_fogintensity;
212 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
213 unsigned int r_numqueries;
214 unsigned int r_maxqueries;
216 typedef struct r_qwskincache_s
218 char name[MAX_QPATH];
219 skinframe_t *skinframe;
223 static r_qwskincache_t *r_qwskincache;
224 static int r_qwskincache_size;
226 /// vertex coordinates for a quad that covers the screen exactly
227 const float r_screenvertex3f[12] =
235 extern void R_DrawModelShadows(void);
237 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
240 for (i = 0;i < verts;i++)
251 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
254 for (i = 0;i < verts;i++)
264 // FIXME: move this to client?
267 if (gamemode == GAME_NEHAHRA)
269 Cvar_Set("gl_fogenable", "0");
270 Cvar_Set("gl_fogdensity", "0.2");
271 Cvar_Set("gl_fogred", "0.3");
272 Cvar_Set("gl_foggreen", "0.3");
273 Cvar_Set("gl_fogblue", "0.3");
275 r_refdef.fog_density = 0;
276 r_refdef.fog_red = 0;
277 r_refdef.fog_green = 0;
278 r_refdef.fog_blue = 0;
279 r_refdef.fog_alpha = 1;
280 r_refdef.fog_start = 0;
281 r_refdef.fog_end = 16384;
282 r_refdef.fog_height = 1<<30;
283 r_refdef.fog_fadedepth = 128;
286 static void R_BuildBlankTextures(void)
288 unsigned char data[4];
289 data[2] = 128; // normal X
290 data[1] = 128; // normal Y
291 data[0] = 255; // normal Z
292 data[3] = 128; // height
293 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
298 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
303 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
308 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
311 static void R_BuildNoTexture(void)
314 unsigned char pix[16][16][4];
315 // this makes a light grey/dark grey checkerboard texture
316 for (y = 0;y < 16;y++)
318 for (x = 0;x < 16;x++)
320 if ((y < 8) ^ (x < 8))
336 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
339 static void R_BuildWhiteCube(void)
341 unsigned char data[6*1*1*4];
342 memset(data, 255, sizeof(data));
343 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
346 static void R_BuildNormalizationCube(void)
350 vec_t s, t, intensity;
353 data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
354 for (side = 0;side < 6;side++)
356 for (y = 0;y < NORMSIZE;y++)
358 for (x = 0;x < NORMSIZE;x++)
360 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
361 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
396 intensity = 127.0f / sqrt(DotProduct(v, v));
397 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
398 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
399 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
400 data[((side*64+y)*64+x)*4+3] = 255;
404 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
408 static void R_BuildFogTexture(void)
412 unsigned char data1[FOGWIDTH][4];
413 //unsigned char data2[FOGWIDTH][4];
416 r_refdef.fogmasktable_start = r_refdef.fog_start;
417 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
418 r_refdef.fogmasktable_range = r_refdef.fogrange;
419 r_refdef.fogmasktable_density = r_refdef.fog_density;
421 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
422 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
424 d = (x * r - r_refdef.fogmasktable_start);
425 if(developer_extra.integer)
426 Con_DPrintf("%f ", d);
428 if (r_fog_exp2.integer)
429 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
431 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
432 if(developer_extra.integer)
433 Con_DPrintf(" : %f ", alpha);
434 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
435 if(developer_extra.integer)
436 Con_DPrintf(" = %f\n", alpha);
437 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
440 for (x = 0;x < FOGWIDTH;x++)
442 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
447 //data2[x][0] = 255 - b;
448 //data2[x][1] = 255 - b;
449 //data2[x][2] = 255 - b;
452 if (r_texture_fogattenuation)
454 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
455 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
459 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);
460 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
464 //=======================================================================================================================================================
466 static const char *builtinshaderstring =
467 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
468 "// written by Forest 'LordHavoc' Hale\n"
469 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
471 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
474 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
475 "#define USELIGHTMAP\n"
477 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
478 "#define USEEYEVECTOR\n"
481 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
482 "# extension GL_ARB_texture_rectangle : enable\n"
485 "#ifdef USESHADOWMAP2D\n"
486 "# ifdef GL_EXT_gpu_shader4\n"
487 "# extension GL_EXT_gpu_shader4 : enable\n"
489 "# ifdef GL_ARB_texture_gather\n"
490 "# extension GL_ARB_texture_gather : enable\n"
492 "# ifdef GL_AMD_texture_texture4\n"
493 "# extension GL_AMD_texture_texture4 : enable\n"
498 "#ifdef USESHADOWMAPCUBE\n"
499 "# extension GL_EXT_gpu_shader4 : enable\n"
502 "//#ifdef USESHADOWSAMPLER\n"
503 "//# extension GL_ARB_shadow : enable\n"
506 "//#ifdef __GLSL_CG_DATA_TYPES\n"
507 "//# define myhalf half\n"
508 "//# define myhalf2 half2\n"
509 "//# define myhalf3 half3\n"
510 "//# define myhalf4 half4\n"
512 "# define myhalf float\n"
513 "# define myhalf2 vec2\n"
514 "# define myhalf3 vec3\n"
515 "# define myhalf4 vec4\n"
518 "#ifdef VERTEX_SHADER\n"
519 "uniform mat4 ModelViewProjectionMatrix;\n"
522 "#ifdef MODE_DEPTH_OR_SHADOW\n"
523 "#ifdef VERTEX_SHADER\n"
526 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
529 "#else // !MODE_DEPTH_ORSHADOW\n"
534 "#ifdef MODE_SHOWDEPTH\n"
535 "#ifdef VERTEX_SHADER\n"
538 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
539 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
543 "#ifdef FRAGMENT_SHADER\n"
546 " gl_FragColor = gl_Color;\n"
549 "#else // !MODE_SHOWDEPTH\n"
554 "#ifdef MODE_POSTPROCESS\n"
555 "varying vec2 TexCoord1;\n"
556 "varying vec2 TexCoord2;\n"
558 "#ifdef VERTEX_SHADER\n"
561 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
562 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
564 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
569 "#ifdef FRAGMENT_SHADER\n"
570 "uniform sampler2D Texture_First;\n"
572 "uniform sampler2D Texture_Second;\n"
574 "#ifdef USEGAMMARAMPS\n"
575 "uniform sampler2D Texture_GammaRamps;\n"
577 "#ifdef USESATURATION\n"
578 "uniform float Saturation;\n"
580 "#ifdef USEVIEWTINT\n"
581 "uniform vec4 ViewTintColor;\n"
583 "//uncomment these if you want to use them:\n"
584 "uniform vec4 UserVec1;\n"
585 "// uniform vec4 UserVec2;\n"
586 "// uniform vec4 UserVec3;\n"
587 "// uniform vec4 UserVec4;\n"
588 "// uniform float ClientTime;\n"
589 "uniform vec2 PixelSize;\n"
592 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
594 " gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
596 "#ifdef USEVIEWTINT\n"
597 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
600 "#ifdef USEPOSTPROCESSING\n"
601 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
602 "// 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"
603 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
604 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
605 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
606 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
607 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
608 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
611 "#ifdef USESATURATION\n"
612 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
613 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
614 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
615 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
618 "#ifdef USEGAMMARAMPS\n"
619 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
620 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
621 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
625 "#else // !MODE_POSTPROCESS\n"
630 "#ifdef MODE_GENERIC\n"
631 "#ifdef USEDIFFUSE\n"
632 "varying vec2 TexCoord1;\n"
634 "#ifdef USESPECULAR\n"
635 "varying vec2 TexCoord2;\n"
637 "#ifdef VERTEX_SHADER\n"
640 " gl_FrontColor = gl_Color;\n"
641 "#ifdef USEDIFFUSE\n"
642 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
644 "#ifdef USESPECULAR\n"
645 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
647 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
651 "#ifdef FRAGMENT_SHADER\n"
652 "#ifdef USEDIFFUSE\n"
653 "uniform sampler2D Texture_First;\n"
655 "#ifdef USESPECULAR\n"
656 "uniform sampler2D Texture_Second;\n"
661 " gl_FragColor = gl_Color;\n"
662 "#ifdef USEDIFFUSE\n"
663 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
666 "#ifdef USESPECULAR\n"
667 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
668 "# ifdef USECOLORMAPPING\n"
669 " gl_FragColor *= tex2;\n"
672 " gl_FragColor += tex2;\n"
674 "# ifdef USEVERTEXTEXTUREBLEND\n"
675 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
680 "#else // !MODE_GENERIC\n"
685 "#ifdef MODE_BLOOMBLUR\n"
686 "varying TexCoord;\n"
687 "#ifdef VERTEX_SHADER\n"
690 " gl_FrontColor = gl_Color;\n"
691 " TexCoord = gl_MultiTexCoord0.xy;\n"
692 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
696 "#ifdef FRAGMENT_SHADER\n"
697 "uniform sampler2D Texture_First;\n"
698 "uniform vec4 BloomBlur_Parameters;\n"
703 " vec2 tc = TexCoord;\n"
704 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
705 " tc += BloomBlur_Parameters.xy;\n"
706 " for (i = 1;i < SAMPLES;i++)\n"
708 " color += texture2D(Texture_First, tc).rgb;\n"
709 " tc += BloomBlur_Parameters.xy;\n"
711 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
714 "#else // !MODE_BLOOMBLUR\n"
715 "#ifdef MODE_REFRACTION\n"
716 "varying vec2 TexCoord;\n"
717 "varying vec4 ModelViewProjectionPosition;\n"
718 "uniform mat4 TexMatrix;\n"
719 "#ifdef VERTEX_SHADER\n"
723 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
724 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
725 " ModelViewProjectionPosition = gl_Position;\n"
729 "#ifdef FRAGMENT_SHADER\n"
730 "uniform sampler2D Texture_Normal;\n"
731 "uniform sampler2D Texture_Refraction;\n"
732 "uniform sampler2D Texture_Reflection;\n"
734 "uniform vec4 DistortScaleRefractReflect;\n"
735 "uniform vec4 ScreenScaleRefractReflect;\n"
736 "uniform vec4 ScreenCenterRefractReflect;\n"
737 "uniform vec4 RefractColor;\n"
738 "uniform vec4 ReflectColor;\n"
739 "uniform float ReflectFactor;\n"
740 "uniform float ReflectOffset;\n"
744 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
745 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
746 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
747 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
748 " // FIXME temporary hack to detect the case that the reflection\n"
749 " // gets blackened at edges due to leaving the area that contains actual\n"
751 " // Remove this 'ack once we have a better way to stop this thing from\n"
753 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
754 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
755 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
756 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
757 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
758 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
761 "#else // !MODE_REFRACTION\n"
766 "#ifdef MODE_WATER\n"
767 "varying vec2 TexCoord;\n"
768 "varying vec3 EyeVector;\n"
769 "varying vec4 ModelViewProjectionPosition;\n"
770 "#ifdef VERTEX_SHADER\n"
771 "uniform vec3 EyePosition;\n"
772 "uniform mat4 TexMatrix;\n"
776 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
777 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
778 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
779 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
780 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
781 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
782 " ModelViewProjectionPosition = gl_Position;\n"
786 "#ifdef FRAGMENT_SHADER\n"
787 "uniform sampler2D Texture_Normal;\n"
788 "uniform sampler2D Texture_Refraction;\n"
789 "uniform sampler2D Texture_Reflection;\n"
791 "uniform vec4 DistortScaleRefractReflect;\n"
792 "uniform vec4 ScreenScaleRefractReflect;\n"
793 "uniform vec4 ScreenCenterRefractReflect;\n"
794 "uniform vec4 RefractColor;\n"
795 "uniform vec4 ReflectColor;\n"
796 "uniform float ReflectFactor;\n"
797 "uniform float ReflectOffset;\n"
801 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
802 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
803 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
804 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
805 " // FIXME temporary hack to detect the case that the reflection\n"
806 " // gets blackened at edges due to leaving the area that contains actual\n"
808 " // Remove this 'ack once we have a better way to stop this thing from\n"
810 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
811 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
812 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
813 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
814 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
815 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
816 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
817 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
818 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
819 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
820 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
821 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
824 "#else // !MODE_WATER\n"
829 "// common definitions between vertex shader and fragment shader:\n"
831 "varying vec2 TexCoord;\n"
832 "#ifdef USEVERTEXTEXTUREBLEND\n"
833 "varying vec2 TexCoord2;\n"
835 "#ifdef USELIGHTMAP\n"
836 "varying vec2 TexCoordLightmap;\n"
839 "#ifdef MODE_LIGHTSOURCE\n"
840 "varying vec3 CubeVector;\n"
843 "#ifdef MODE_LIGHTSOURCE\n"
844 "varying vec3 LightVector;\n"
846 "#if defined(MODE_LIGHTDIRECTION)\n"
847 "varying vec3 LightVector;\n"
850 "#ifdef USEEYEVECTOR\n"
851 "varying vec3 EyeVector;\n"
854 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
858 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
859 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
860 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
863 "#ifdef USEREFLECTION\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
866 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
867 "uniform vec3 LightPosition;\n"
868 "varying vec4 ModelViewPosition;\n"
871 "#ifdef MODE_LIGHTSOURCE\n"
872 "uniform vec3 LightPosition;\n"
874 "uniform vec3 EyePosition;\n"
875 "#ifdef MODE_LIGHTDIRECTION\n"
876 "uniform vec3 LightDir;\n"
878 "uniform vec4 FogPlane;\n"
884 "// 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"
886 "// fragment shader specific:\n"
887 "#ifdef FRAGMENT_SHADER\n"
889 "uniform sampler2D Texture_Normal;\n"
890 "uniform sampler2D Texture_Color;\n"
891 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
892 "uniform sampler2D Texture_Gloss;\n"
895 "uniform sampler2D Texture_Glow;\n"
897 "#ifdef USEVERTEXTEXTUREBLEND\n"
898 "uniform sampler2D Texture_SecondaryNormal;\n"
899 "uniform sampler2D Texture_SecondaryColor;\n"
900 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
901 "uniform sampler2D Texture_SecondaryGloss;\n"
904 "uniform sampler2D Texture_SecondaryGlow;\n"
907 "#ifdef USECOLORMAPPING\n"
908 "uniform sampler2D Texture_Pants;\n"
909 "uniform sampler2D Texture_Shirt;\n"
912 "uniform sampler2D Texture_FogMask;\n"
914 "#ifdef USELIGHTMAP\n"
915 "uniform sampler2D Texture_Lightmap;\n"
917 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
918 "uniform sampler2D Texture_Deluxemap;\n"
920 "#ifdef USEREFLECTION\n"
921 "uniform sampler2D Texture_Reflection;\n"
924 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
925 "uniform sampler2DRect Texture_ScreenDepth;\n"
926 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
928 "#ifdef USEDEFERREDLIGHTMAP\n"
929 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
930 "uniform sampler2DRect Texture_ScreenSpecular;\n"
933 "uniform myhalf3 Color_Pants;\n"
934 "uniform myhalf3 Color_Shirt;\n"
935 "uniform myhalf3 FogColor;\n"
938 "uniform float FogRangeRecip;\n"
939 "uniform float FogPlaneViewDist;\n"
940 "uniform float FogHeightFade;\n"
941 "float FogVertex(void)\n"
943 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
944 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
946 "#ifdef USEFOGOUTSIDE\n"
947 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
949 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
951 " return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
955 "#ifdef USEOFFSETMAPPING\n"
956 "uniform float OffsetMapping_Scale;\n"
957 "vec2 OffsetMapping(vec2 TexCoord)\n"
959 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
960 " // 14 sample relief mapping: linear search and then binary search\n"
961 " // this basically steps forward a small amount repeatedly until it finds\n"
962 " // itself inside solid, then jitters forward and back using decreasing\n"
963 " // amounts to find the impact\n"
964 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
965 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
966 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
967 " vec3 RT = vec3(TexCoord, 1);\n"
968 " OffsetVector *= 0.1;\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);\n"
974 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
975 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
976 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
977 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
978 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
979 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
980 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
981 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
982 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
985 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
986 " // this basically moves forward the full distance, and then backs up based\n"
987 " // on height of samples\n"
988 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
989 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
990 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
991 " TexCoord += OffsetVector;\n"
992 " OffsetVector *= 0.333;\n"
993 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
994 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
995 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
996 " return TexCoord;\n"
999 "#endif // USEOFFSETMAPPING\n"
1001 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1002 "uniform sampler2D Texture_Attenuation;\n"
1003 "uniform samplerCube Texture_Cube;\n"
1005 "#ifdef USESHADOWMAPRECT\n"
1006 "# ifdef USESHADOWSAMPLER\n"
1007 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1009 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1013 "#ifdef USESHADOWMAP2D\n"
1014 "# ifdef USESHADOWSAMPLER\n"
1015 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1017 "uniform sampler2D Texture_ShadowMap2D;\n"
1021 "#ifdef USESHADOWMAPVSDCT\n"
1022 "uniform samplerCube Texture_CubeProjection;\n"
1025 "#ifdef USESHADOWMAPCUBE\n"
1026 "# ifdef USESHADOWSAMPLER\n"
1027 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1029 "uniform samplerCube Texture_ShadowMapCube;\n"
1033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1034 "uniform vec2 ShadowMap_TextureScale;\n"
1035 "uniform vec4 ShadowMap_Parameters;\n"
1038 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1039 "# ifndef USESHADOWMAPVSDCT\n"
1040 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1042 " vec3 adir = abs(dir);\n"
1046 " if (adir.x > adir.y)\n"
1048 " if (adir.x > adir.z) // X\n"
1052 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1058 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1063 " if (adir.y > adir.z) // Y\n"
1067 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1073 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1077 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1078 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1079 " stc.z += ShadowMap_Parameters.z;\n"
1083 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1085 " vec3 adir = abs(dir);\n"
1086 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1087 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1088 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1089 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1090 " stc.z += ShadowMap_Parameters.z;\n"
1094 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1096 "#ifdef USESHADOWMAPCUBE\n"
1097 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1099 " vec3 adir = abs(dir);\n"
1100 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1104 "# ifdef USESHADOWMAPRECT\n"
1105 "float ShadowMapCompare(vec3 dir)\n"
1107 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1109 "# ifdef USESHADOWSAMPLER\n"
1111 "# ifdef USESHADOWMAPPCF\n"
1112 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1113 " 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"
1115 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1120 "# ifdef USESHADOWMAPPCF\n"
1121 "# if USESHADOWMAPPCF > 1\n"
1122 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1123 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1124 " 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"
1125 " 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"
1126 " 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"
1127 " 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"
1128 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1129 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1131 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1132 " vec2 offset = fract(shadowmaptc.xy);\n"
1133 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1134 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1135 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1136 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1137 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1140 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1148 "# ifdef USESHADOWMAP2D\n"
1149 "float ShadowMapCompare(vec3 dir)\n"
1151 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1154 "# ifdef USESHADOWSAMPLER\n"
1155 "# ifdef USESHADOWMAPPCF\n"
1156 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1157 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1158 " 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"
1160 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1163 "# ifdef USESHADOWMAPPCF\n"
1164 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1165 "# ifdef GL_ARB_texture_gather\n"
1166 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1168 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1170 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1171 " center *= ShadowMap_TextureScale;\n"
1172 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1173 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1174 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1175 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1176 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1177 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1178 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1180 "# ifdef GL_EXT_gpu_shader4\n"
1181 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1183 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1185 "# if USESHADOWMAPPCF > 1\n"
1186 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1187 " center *= ShadowMap_TextureScale;\n"
1188 " 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"
1189 " 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"
1190 " 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"
1191 " 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"
1192 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1193 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1195 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1196 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1197 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1198 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1199 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1200 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1204 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1211 "# ifdef USESHADOWMAPCUBE\n"
1212 "float ShadowMapCompare(vec3 dir)\n"
1214 " // apply depth texture cubemap as light filter\n"
1215 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1217 "# ifdef USESHADOWSAMPLER\n"
1218 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1220 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1225 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1226 "#endif // FRAGMENT_SHADER\n"
1231 "#ifdef MODE_DEFERREDGEOMETRY\n"
1232 "#ifdef VERTEX_SHADER\n"
1233 "uniform mat4 TexMatrix;\n"
1234 "#ifdef USEVERTEXTEXTUREBLEND\n"
1235 "uniform mat4 BackgroundTexMatrix;\n"
1237 "uniform mat4 ModelViewMatrix;\n"
1240 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1241 "#ifdef USEVERTEXTEXTUREBLEND\n"
1242 " gl_FrontColor = gl_Color;\n"
1243 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1246 " // transform unnormalized eye direction into tangent space\n"
1247 "#ifdef USEOFFSETMAPPING\n"
1248 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1249 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1250 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1251 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1254 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1255 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1256 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1257 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1259 "#endif // VERTEX_SHADER\n"
1261 "#ifdef FRAGMENT_SHADER\n"
1264 "#ifdef USEOFFSETMAPPING\n"
1265 " // apply offsetmapping\n"
1266 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1267 "#define TexCoord TexCoordOffset\n"
1270 "#ifdef USEALPHAKILL\n"
1271 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1275 "#ifdef USEVERTEXTEXTUREBLEND\n"
1276 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1277 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1278 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1279 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1282 "#ifdef USEVERTEXTEXTUREBLEND\n"
1283 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1285 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1288 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1290 "#endif // FRAGMENT_SHADER\n"
1291 "#else // !MODE_DEFERREDGEOMETRY\n"
1296 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1297 "#ifdef VERTEX_SHADER\n"
1298 "uniform mat4 ModelViewMatrix;\n"
1301 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1302 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1304 "#endif // VERTEX_SHADER\n"
1306 "#ifdef FRAGMENT_SHADER\n"
1307 "uniform mat4 ViewToLight;\n"
1308 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1309 "uniform vec2 ScreenToDepth;\n"
1310 "uniform myhalf3 DeferredColor_Ambient;\n"
1311 "uniform myhalf3 DeferredColor_Diffuse;\n"
1312 "#ifdef USESPECULAR\n"
1313 "uniform myhalf3 DeferredColor_Specular;\n"
1314 "uniform myhalf SpecularPower;\n"
1318 " // calculate viewspace pixel position\n"
1320 " position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1321 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1322 " // decode viewspace pixel normal\n"
1323 " myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1324 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1325 " // surfacenormal = pixel normal in viewspace\n"
1326 " // LightVector = pixel to light in viewspace\n"
1327 " // CubeVector = position in lightspace\n"
1328 " // eyevector = pixel to view in viewspace\n"
1329 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1330 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1331 "#ifdef USEDIFFUSE\n"
1332 " // calculate diffuse shading\n"
1333 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1334 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1336 "#ifdef USESPECULAR\n"
1337 " // calculate directional shading\n"
1338 " vec3 eyevector = position * -1.0;\n"
1339 "# ifdef USEEXACTSPECULARMATH\n"
1340 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1342 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1343 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1347 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1348 " fade *= ShadowMapCompare(CubeVector);\n"
1351 "#ifdef USEDIFFUSE\n"
1352 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1354 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1356 "#ifdef USESPECULAR\n"
1357 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1359 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1362 "# ifdef USECUBEFILTER\n"
1363 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1364 " gl_FragData[0] *= cubecolor;\n"
1365 " gl_FragData[1] *= cubecolor;\n"
1368 "#endif // FRAGMENT_SHADER\n"
1369 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1374 "#ifdef VERTEX_SHADER\n"
1375 "uniform mat4 TexMatrix;\n"
1376 "#ifdef USEVERTEXTEXTUREBLEND\n"
1377 "uniform mat4 BackgroundTexMatrix;\n"
1379 "#ifdef MODE_LIGHTSOURCE\n"
1380 "uniform mat4 ModelToLight;\n"
1384 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1385 " gl_FrontColor = gl_Color;\n"
1387 " // copy the surface texcoord\n"
1388 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1392 "#ifdef USELIGHTMAP\n"
1393 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1396 "#ifdef MODE_LIGHTSOURCE\n"
1397 " // transform vertex position into light attenuation/cubemap space\n"
1398 " // (-1 to +1 across the light box)\n"
1399 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1401 "# ifdef USEDIFFUSE\n"
1402 " // transform unnormalized light direction into tangent space\n"
1403 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1404 " // normalize it per pixel)\n"
1405 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1406 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1407 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1408 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1412 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1413 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1414 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1415 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1418 " // transform unnormalized eye direction into tangent space\n"
1419 "#ifdef USEEYEVECTOR\n"
1420 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1421 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1422 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1423 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1427 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1428 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1431 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1432 " VectorS = gl_MultiTexCoord1.xyz;\n"
1433 " VectorT = gl_MultiTexCoord2.xyz;\n"
1434 " VectorR = gl_MultiTexCoord3.xyz;\n"
1437 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1438 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1440 "#ifdef USEREFLECTION\n"
1441 " ModelViewProjectionPosition = gl_Position;\n"
1444 "#endif // VERTEX_SHADER\n"
1449 "#ifdef FRAGMENT_SHADER\n"
1450 "#ifdef USEDEFERREDLIGHTMAP\n"
1451 "uniform myhalf3 DeferredMod_Diffuse;\n"
1452 "uniform myhalf3 DeferredMod_Specular;\n"
1454 "uniform myhalf3 Color_Ambient;\n"
1455 "uniform myhalf3 Color_Diffuse;\n"
1456 "uniform myhalf3 Color_Specular;\n"
1457 "uniform myhalf SpecularPower;\n"
1459 "uniform myhalf3 Color_Glow;\n"
1461 "uniform myhalf Alpha;\n"
1462 "#ifdef USEREFLECTION\n"
1463 "uniform vec4 DistortScaleRefractReflect;\n"
1464 "uniform vec4 ScreenScaleRefractReflect;\n"
1465 "uniform vec4 ScreenCenterRefractReflect;\n"
1466 "uniform myhalf4 ReflectColor;\n"
1468 "#ifdef MODE_LIGHTDIRECTION\n"
1469 "uniform myhalf3 LightColor;\n"
1471 "#ifdef MODE_LIGHTSOURCE\n"
1472 "uniform myhalf3 LightColor;\n"
1476 "#ifdef USEOFFSETMAPPING\n"
1477 " // apply offsetmapping\n"
1478 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1479 "#define TexCoord TexCoordOffset\n"
1482 " // combine the diffuse textures (base, pants, shirt)\n"
1483 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1484 "#ifdef USEALPHAKILL\n"
1485 " if (color.a < 0.5)\n"
1488 " color.a *= Alpha;\n"
1489 "#ifdef USECOLORMAPPING\n"
1490 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1492 "#ifdef USEVERTEXTEXTUREBLEND\n"
1493 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1494 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1495 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1496 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1498 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1501 " // get the surface normal\n"
1502 "#ifdef USEVERTEXTEXTUREBLEND\n"
1503 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1505 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1508 " // get the material colors\n"
1509 " myhalf3 diffusetex = color.rgb;\n"
1510 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1511 "# ifdef USEVERTEXTEXTUREBLEND\n"
1512 " myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1514 " myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1521 "#ifdef MODE_LIGHTSOURCE\n"
1522 " // light source\n"
1523 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1524 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1525 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1526 "#ifdef USESPECULAR\n"
1527 "#ifdef USEEXACTSPECULARMATH\n"
1528 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1530 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1531 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1533 " color.rgb += glosstex * (specular * Color_Specular);\n"
1535 " color.rgb *= LightColor;\n"
1536 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1537 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1538 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1540 "# ifdef USECUBEFILTER\n"
1541 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1543 "#endif // MODE_LIGHTSOURCE\n"
1548 "#ifdef MODE_LIGHTDIRECTION\n"
1550 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1551 "#define lightcolor LightColor\n"
1552 "#endif // MODE_LIGHTDIRECTION\n"
1553 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1555 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1556 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1557 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1558 " // convert modelspace light vector to tangentspace\n"
1559 " myhalf3 lightnormal;\n"
1560 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1561 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1562 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1563 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1564 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1565 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1566 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1567 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1568 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1569 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1570 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1571 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1572 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1573 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1574 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1576 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1577 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1578 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1584 "#ifdef MODE_LIGHTMAP\n"
1585 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1586 "#endif // MODE_LIGHTMAP\n"
1587 "#ifdef MODE_VERTEXCOLOR\n"
1588 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1589 "#endif // MODE_VERTEXCOLOR\n"
1590 "#ifdef MODE_FLATCOLOR\n"
1591 " color.rgb = diffusetex * Color_Ambient;\n"
1592 "#endif // MODE_FLATCOLOR\n"
1598 "# ifdef USEDIFFUSE\n"
1599 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1600 "# ifdef USESPECULAR\n"
1601 "# ifdef USEEXACTSPECULARMATH\n"
1602 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1604 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1605 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1607 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1609 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1612 " color.rgb = diffusetex * Color_Ambient;\n"
1616 "#ifdef USEDEFERREDLIGHTMAP\n"
1617 " color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1618 " color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1622 "#ifdef USEVERTEXTEXTUREBLEND\n"
1623 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1625 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1630 "#ifdef MODE_LIGHTSOURCE\n"
1631 " color.rgb *= myhalf(FogVertex());\n"
1633 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1637 " // 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"
1638 "#ifdef USEREFLECTION\n"
1639 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1640 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1641 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1642 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1643 " // FIXME temporary hack to detect the case that the reflection\n"
1644 " // gets blackened at edges due to leaving the area that contains actual\n"
1646 " // Remove this 'ack once we have a better way to stop this thing from\n"
1648 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1649 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1650 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1651 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1652 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1653 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1656 " gl_FragColor = vec4(color);\n"
1658 "#endif // FRAGMENT_SHADER\n"
1660 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1661 "#endif // !MODE_DEFERREDGEOMETRY\n"
1662 "#endif // !MODE_WATER\n"
1663 "#endif // !MODE_REFRACTION\n"
1664 "#endif // !MODE_BLOOMBLUR\n"
1665 "#endif // !MODE_GENERIC\n"
1666 "#endif // !MODE_POSTPROCESS\n"
1667 "#endif // !MODE_SHOWDEPTH\n"
1668 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1672 =========================================================================================================================================================
1676 =========================================================================================================================================================
1680 =========================================================================================================================================================
1684 =========================================================================================================================================================
1688 =========================================================================================================================================================
1692 =========================================================================================================================================================
1696 =========================================================================================================================================================
1699 const char *builtincgshaderstring =
1700 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1701 "// written by Forest 'LordHavoc' Hale\n"
1702 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1704 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1707 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1708 "#define USELIGHTMAP\n"
1710 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1711 "#define USEEYEVECTOR\n"
1714 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1715 "#ifdef VERTEX_SHADER\n"
1718 "float4 gl_Vertex : POSITION,\n"
1719 "uniform float4x4 ModelViewProjectionMatrix,\n"
1720 "out float4 gl_Position : POSITION\n"
1723 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1726 "#else // !MODE_DEPTH_ORSHADOW\n"
1731 "#ifdef MODE_SHOWDEPTH\n"
1732 "#ifdef VERTEX_SHADER\n"
1735 "float4 gl_Vertex : POSITION,\n"
1736 "uniform float4x4 ModelViewProjectionMatrix,\n"
1737 "out float4 gl_Position : POSITION,\n"
1738 "out float4 gl_FrontColor : COLOR0\n"
1741 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1742 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1746 "#ifdef FRAGMENT_SHADER\n"
1749 "float4 gl_FrontColor : COLOR0,\n"
1750 "out float4 gl_FragColor : COLOR\n"
1753 " gl_FragColor = gl_FrontColor;\n"
1756 "#else // !MODE_SHOWDEPTH\n"
1761 "#ifdef MODE_POSTPROCESS\n"
1763 "#ifdef VERTEX_SHADER\n"
1766 "float4 gl_Vertex : POSITION,\n"
1767 "uniform float4x4 ModelViewProjectionMatrix,\n"
1768 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1769 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1770 "out float4 gl_Position : POSITION,\n"
1771 "out float2 TexCoord1 : TEXCOORD0,\n"
1772 "out float2 TexCoord2 : TEXCOORD1\n"
1775 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1776 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1778 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1783 "#ifdef FRAGMENT_SHADER\n"
1786 "float2 TexCoord1 : TEXCOORD0,\n"
1787 "float2 TexCoord2 : TEXCOORD1,\n"
1788 "uniform sampler2D Texture_First,\n"
1790 "uniform sampler2D Texture_Second,\n"
1792 "#ifdef USEGAMMARAMPS\n"
1793 "uniform sampler2D Texture_GammaRamps,\n"
1795 "#ifdef USESATURATION\n"
1796 "uniform float Saturation,\n"
1798 "#ifdef USEVIEWTINT\n"
1799 "uniform float4 ViewTintColor,\n"
1801 "uniform float4 UserVec1,\n"
1802 "uniform float4 UserVec2,\n"
1803 "uniform float4 UserVec3,\n"
1804 "uniform float4 UserVec4,\n"
1805 "uniform float ClientTime,\n"
1806 "uniform float2 PixelSize,\n"
1807 "out float4 gl_FragColor : COLOR\n"
1810 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1812 " gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1814 "#ifdef USEVIEWTINT\n"
1815 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1818 "#ifdef USEPOSTPROCESSING\n"
1819 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1820 "// 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"
1821 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1822 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1823 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1824 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
1825 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
1826 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1829 "#ifdef USESATURATION\n"
1830 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1831 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1832 " //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1833 " gl_FragColor.rgb = mix(float3(y), gl_FragColor.rgb, Saturation);\n"
1836 "#ifdef USEGAMMARAMPS\n"
1837 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1838 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1839 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1843 "#else // !MODE_POSTPROCESS\n"
1848 "#ifdef MODE_GENERIC\n"
1849 "#ifdef VERTEX_SHADER\n"
1852 "float4 gl_Vertex : POSITION,\n"
1853 "uniform float4x4 ModelViewProjectionMatrix,\n"
1854 "float4 gl_Color : COLOR0,\n"
1855 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1856 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1857 "out float4 gl_Position : POSITION,\n"
1858 "out float4 gl_FrontColor : COLOR,\n"
1859 "out float2 TexCoord1 : TEXCOORD0,\n"
1860 "out float2 TexCoord2 : TEXCOORD1\n"
1863 " gl_FrontColor = gl_Color;\n"
1864 "#ifdef USEDIFFUSE\n"
1865 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1867 "#ifdef USESPECULAR\n"
1868 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1870 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1874 "#ifdef FRAGMENT_SHADER\n"
1878 "float4 gl_FrontColor : COLOR,\n"
1879 "float2 TexCoord1 : TEXCOORD0,\n"
1880 "float2 TexCoord2 : TEXCOORD1,\n"
1881 "#ifdef USEDIFFUSE\n"
1882 "uniform sampler2D Texture_First,\n"
1884 "#ifdef USESPECULAR\n"
1885 "uniform sampler2D Texture_Second,\n"
1887 "out float4 gl_FragColor : COLOR\n"
1890 " gl_FragColor = gl_FrontColor;\n"
1891 "#ifdef USEDIFFUSE\n"
1892 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1895 "#ifdef USESPECULAR\n"
1896 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1897 "# ifdef USECOLORMAPPING\n"
1898 " gl_FragColor *= tex2;\n"
1901 " gl_FragColor += tex2;\n"
1903 "# ifdef USEVERTEXTEXTUREBLEND\n"
1904 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
1909 "#else // !MODE_GENERIC\n"
1914 "#ifdef MODE_BLOOMBLUR\n"
1915 "#ifdef VERTEX_SHADER\n"
1918 "float4 gl_Vertex : POSITION,\n"
1919 "uniform float4x4 ModelViewProjectionMatrix,\n"
1920 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1921 "out float4 gl_Position : POSITION,\n"
1922 "out float2 TexCoord : TEXCOORD0\n"
1925 " TexCoord = gl_MultiTexCoord0.xy;\n"
1926 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1930 "#ifdef FRAGMENT_SHADER\n"
1934 "float2 TexCoord : TEXCOORD0,\n"
1935 "uniform sampler2D Texture_First,\n"
1936 "uniform float4 BloomBlur_Parameters,\n"
1937 "out float4 gl_FragColor : COLOR\n"
1941 " float2 tc = TexCoord;\n"
1942 " float3 color = tex2D(Texture_First, tc).rgb;\n"
1943 " tc += BloomBlur_Parameters.xy;\n"
1944 " for (i = 1;i < SAMPLES;i++)\n"
1946 " color += tex2D(Texture_First, tc).rgb;\n"
1947 " tc += BloomBlur_Parameters.xy;\n"
1949 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1952 "#else // !MODE_BLOOMBLUR\n"
1953 "#ifdef MODE_REFRACTION\n"
1954 "#ifdef VERTEX_SHADER\n"
1957 "float4 gl_Vertex : POSITION,\n"
1958 "uniform float4x4 ModelViewProjectionMatrix,\n"
1959 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1960 "uniform mat4 TexMatrix,\n"
1961 "uniform float3 EyePosition,\n"
1962 "out float4 gl_Position : POSITION,\n"
1963 "out float2 TexCoord : TEXCOORD0,\n"
1964 "out float3 EyeVector : TEXCOORD1,\n"
1965 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1968 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1969 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1970 " ModelViewProjectionPosition = gl_Position;\n"
1974 "#ifdef FRAGMENT_SHADER\n"
1977 "float2 TexCoord : TEXCOORD0,\n"
1978 "float3 EyeVector : TEXCOORD1,\n"
1979 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1980 "uniform sampler2D Texture_Normal,\n"
1981 "uniform sampler2D Texture_Refraction,\n"
1982 "uniform sampler2D Texture_Reflection,\n"
1983 "uniform float4 DistortScaleRefractReflect,\n"
1984 "uniform float4 ScreenScaleRefractReflect,\n"
1985 "uniform float4 ScreenCenterRefractReflect,\n"
1986 "uniform float4 RefractColor,\n"
1987 "out float4 gl_FragColor : COLOR\n"
1990 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1991 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1992 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1993 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1994 " // FIXME temporary hack to detect the case that the reflection\n"
1995 " // gets blackened at edges due to leaving the area that contains actual\n"
1997 " // Remove this 'ack once we have a better way to stop this thing from\n"
1999 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2000 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2001 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2002 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2003 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2004 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2007 "#else // !MODE_REFRACTION\n"
2012 "#ifdef MODE_WATER\n"
2013 "#ifdef VERTEX_SHADER\n"
2017 "float4 gl_Vertex : POSITION,\n"
2018 "uniform float4x4 ModelViewProjectionMatrix,\n"
2019 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2020 "uniform mat4 TexMatrix,\n"
2021 "uniform float3 EyePosition,\n"
2022 "out float4 gl_Position : POSITION,\n"
2023 "out float2 TexCoord : TEXCOORD0,\n"
2024 "out float3 EyeVector : TEXCOORD1,\n"
2025 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2028 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2029 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2030 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2031 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2032 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2033 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2034 " ModelViewProjectionPosition = gl_Position;\n"
2038 "#ifdef FRAGMENT_SHADER\n"
2041 "float2 TexCoord : TEXCOORD0,\n"
2042 "float3 EyeVector : TEXCOORD1,\n"
2043 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2044 "uniform sampler2D Texture_Normal,\n"
2045 "uniform sampler2D Texture_Refraction,\n"
2046 "uniform sampler2D Texture_Reflection,\n"
2047 "uniform float4 DistortScaleRefractReflect,\n"
2048 "uniform float4 ScreenScaleRefractReflect,\n"
2049 "uniform float4 ScreenCenterRefractReflect,\n"
2050 "uniform float4 RefractColor,\n"
2051 "uniform float4 ReflectColor,\n"
2052 "uniform float ReflectFactor,\n"
2053 "uniform float ReflectOffset,\n"
2054 "out float4 gl_FragColor : COLOR\n"
2057 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2058 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2059 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2060 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2061 " // FIXME temporary hack to detect the case that the reflection\n"
2062 " // gets blackened at edges due to leaving the area that contains actual\n"
2064 " // Remove this 'ack once we have a better way to stop this thing from\n"
2066 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2067 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2068 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2069 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2070 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2071 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2072 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2073 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2074 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2075 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2076 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2077 " gl_FragColor = mix(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2080 "#else // !MODE_WATER\n"
2085 "// 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"
2087 "// fragment shader specific:\n"
2088 "#ifdef FRAGMENT_SHADER\n"
2091 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2094 "#ifdef USEFOGOUTSIDE\n"
2095 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2097 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2099 " return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2103 "#ifdef USEOFFSETMAPPING\n"
2104 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2106 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2107 " // 14 sample relief mapping: linear search and then binary search\n"
2108 " // this basically steps forward a small amount repeatedly until it finds\n"
2109 " // itself inside solid, then jitters forward and back using decreasing\n"
2110 " // amounts to find the impact\n"
2111 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2112 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2113 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2114 " float3 RT = float3(TexCoord, 1);\n"
2115 " OffsetVector *= 0.1;\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);\n"
2121 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2122 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2123 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2124 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2125 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2126 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2127 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2128 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2129 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2132 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2133 " // this basically moves forward the full distance, and then backs up based\n"
2134 " // on height of samples\n"
2135 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2136 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2137 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2138 " TexCoord += OffsetVector;\n"
2139 " OffsetVector *= 0.333;\n"
2140 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2141 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2142 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2143 " return TexCoord;\n"
2146 "#endif // USEOFFSETMAPPING\n"
2148 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2149 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2150 "# ifndef USESHADOWMAPVSDCT\n"
2151 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2153 " float3 adir = abs(dir);\n"
2157 " if (adir.x > adir.y)\n"
2159 " if (adir.x > adir.z) // X\n"
2163 " offset = float2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2169 " offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2174 " if (adir.y > adir.z) // Y\n"
2178 " offset = float2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2184 " offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2188 " float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2189 " stc.xy += offset * ShadowMap_Parameters.y;\n"
2190 " stc.z += ShadowMap_Parameters.z;\n"
2194 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2196 " float3 adir = abs(dir);\n"
2197 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2198 " float ma = max(max(adir.x, adir.y), adir.z);\n"
2199 " float3 stc = float3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2200 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2201 " stc.z += ShadowMap_Parameters.z;\n"
2205 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2207 "#ifdef USESHADOWMAPCUBE\n"
2208 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2210 " float3 adir = abs(dir);\n"
2211 " return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2215 "# ifdef USESHADOWMAPRECT\n"
2216 "#ifdef USESHADOWMAPVSDCT\n"
2217 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2219 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2222 "#ifdef USESHADOWMAPVSDCT\n"
2223 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2225 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2228 "# ifdef USESHADOWSAMPLER\n"
2230 "# ifdef USESHADOWMAPPCF\n"
2231 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2232 " 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"
2234 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2239 "# ifdef USESHADOWMAPPCF\n"
2240 "# if USESHADOWMAPPCF > 1\n"
2241 "# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2242 " float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2243 " 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"
2244 " 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"
2245 " 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"
2246 " 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"
2247 " float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2248 " f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2250 "# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2251 " float2 offset = fract(shadowmaptc.xy);\n"
2252 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2253 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2254 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2255 " float3 cols = row2 + mix(row1, row3, offset.y);\n"
2256 " f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2259 " f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2267 "# ifdef USESHADOWMAP2D\n"
2268 "#ifdef USESHADOWMAPVSDCT\n"
2269 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2271 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2274 "#ifdef USESHADOWMAPVSDCT\n"
2275 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2277 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2281 "# ifdef USESHADOWSAMPLER\n"
2282 "# ifdef USESHADOWMAPPCF\n"
2283 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
2284 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2285 " 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"
2287 " f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2290 "# ifdef USESHADOWMAPPCF\n"
2291 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2292 "# ifdef GL_ARB_texture_gather\n"
2293 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2295 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2297 " float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2298 " center *= ShadowMap_TextureScale;\n"
2299 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2300 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2301 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2302 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2303 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2304 " mix(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2305 " f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2307 "# ifdef GL_EXT_gpu_shader4\n"
2308 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, ifloat2(x, y)).r\n"
2310 "# define texval(x, y) tex2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2312 "# if USESHADOWMAPPCF > 1\n"
2313 " float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2314 " center *= ShadowMap_TextureScale;\n"
2315 " 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"
2316 " 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"
2317 " 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"
2318 " 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"
2319 " float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2320 " f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2322 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
2323 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2324 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2325 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2326 " float3 cols = row2 + mix(row1, row3, offset.y);\n"
2327 " f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2331 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2338 "# ifdef USESHADOWMAPCUBE\n"
2339 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2341 " // apply depth texture cubemap as light filter\n"
2342 " float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2344 "# ifdef USESHADOWSAMPLER\n"
2345 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2347 " f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2352 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2353 "#endif // FRAGMENT_SHADER\n"
2358 "#ifdef MODE_DEFERREDGEOMETRY\n"
2359 "#ifdef VERTEX_SHADER\n"
2362 "float4 gl_Vertex : POSITION,\n"
2363 "uniform float4x4 ModelViewProjectionMatrix,\n"
2364 "#ifdef USEVERTEXTEXTUREBLEND\n"
2365 "float4 gl_Color : COLOR0,\n"
2367 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2368 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2369 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2370 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2371 "uniform mat4 TexMatrix,\n"
2372 "#ifdef USEVERTEXTEXTUREBLEND\n"
2373 "uniform mat4 BackgroundTexMatrix,\n"
2375 "uniform mat4 ModelViewMatrix,\n"
2376 "out float4 gl_Position : POSITION,\n"
2377 "out float4 gl_FrontColor : COLOR,\n"
2378 "out float4 TexCoordBoth : TEXCOORD0,\n"
2379 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2380 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2381 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2384 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2385 "#ifdef USEVERTEXTEXTUREBLEND\n"
2386 " gl_FrontColor = gl_Color;\n"
2387 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2390 " // transform unnormalized eye direction into tangent space\n"
2391 "#ifdef USEOFFSETMAPPING\n"
2392 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2393 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2394 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2395 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2398 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2399 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2400 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2401 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2403 "#endif // VERTEX_SHADER\n"
2405 "#ifdef FRAGMENT_SHADER\n"
2408 "float4 TexCoordBoth : TEXCOORD0,\n"
2409 "float3 EyeVector : TEXCOORD2,\n"
2410 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2411 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2412 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2413 "uniform sampler2D Texture_Normal,\n"
2414 "#ifdef USEALPHAKILL\n"
2415 "uniform sampler2D Texture_Color,\n"
2417 "#ifdef USEVERTEXTEXTUREBLEND\n"
2418 "uniform sampler2D Texture_SecondaryNormal,\n"
2420 "#ifdef USEOFFSETMAPPING\n"
2421 "uniform float OffsetMapping_Scale,\n"
2423 "uniform half SpecularPower,\n"
2424 "out float4 gl_FragColor : COLOR\n"
2427 " float2 TexCoord = TexCoordBoth.xy;\n"
2428 "#ifdef USEOFFSETMAPPING\n"
2429 " // apply offsetmapping\n"
2430 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2431 "#define TexCoord TexCoordOffset\n"
2434 "#ifdef USEALPHAKILL\n"
2435 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2439 "#ifdef USEVERTEXTEXTUREBLEND\n"
2440 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2441 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2442 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2443 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2446 "#ifdef USEVERTEXTEXTUREBLEND\n"
2447 " float3 surfacenormal = mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2449 " float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2452 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2454 "#endif // FRAGMENT_SHADER\n"
2455 "#else // !MODE_DEFERREDGEOMETRY\n"
2460 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2461 "#ifdef VERTEX_SHADER\n"
2464 "float4 gl_Vertex : POSITION,\n"
2465 "uniform float4x4 ModelViewProjectionMatrix,\n"
2466 "uniform mat4 ModelViewMatrix,\n"
2467 "out float4 gl_Position : POSITION,\n"
2468 "out float4 ModelViewPosition : TEXCOORD0\n"
2471 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2472 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2474 "#endif // VERTEX_SHADER\n"
2476 "#ifdef FRAGMENT_SHADER\n"
2479 "float2 Pixel : WPOS,\n"
2480 "float4 ModelViewPosition : TEXCOORD0,\n"
2481 "uniform mat4 ViewToLight,\n"
2482 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2483 "uniform float3 LightPosition,\n"
2484 "uniform half3 DeferredColor_Ambient,\n"
2485 "uniform half3 DeferredColor_Diffuse,\n"
2486 "#ifdef USESPECULAR\n"
2487 "uniform half3 DeferredColor_Specular,\n"
2488 "uniform half SpecularPower,\n"
2490 "uniform sampler2D Texture_Attenuation,\n"
2491 "uniform samplerRECT Texture_ScreenDepth,\n"
2492 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2494 "#ifdef USESHADOWMAPRECT\n"
2495 "# ifdef USESHADOWSAMPLER\n"
2496 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2498 "uniform samplerRECT Texture_ShadowMapRect,\n"
2502 "#ifdef USESHADOWMAP2D\n"
2503 "# ifdef USESHADOWSAMPLER\n"
2504 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2506 "uniform sampler2D Texture_ShadowMap2D,\n"
2510 "#ifdef USESHADOWMAPVSDCT\n"
2511 "uniform samplerCUBE Texture_CubeProjection,\n"
2514 "#ifdef USESHADOWMAPCUBE\n"
2515 "# ifdef USESHADOWSAMPLER\n"
2516 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2518 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2522 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2523 "uniform float2 ShadowMap_TextureScale,\n"
2524 "uniform float4 ShadowMap_Parameters,\n"
2527 "out float4 gl_FragData0 : COLOR0,\n"
2528 "out float4 gl_FragData1 : COLOR1\n"
2531 " // calculate viewspace pixel position\n"
2532 " float3 position;\n"
2533 " position.z = ScreenToDepth.y / (texRECT(Texture_ScreenDepth, Pixel).r + ScreenToDepth.x);\n"
2534 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2535 " // decode viewspace pixel normal\n"
2536 " half4 normalmap = texRECT(Texture_ScreenNormalMap, Pixel);\n"
2537 " half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2538 " // surfacenormal = pixel normal in viewspace\n"
2539 " // LightVector = pixel to light in viewspace\n"
2540 " // CubeVector = position in lightspace\n"
2541 " // eyevector = pixel to view in viewspace\n"
2542 " float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2543 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2544 "#ifdef USEDIFFUSE\n"
2545 " // calculate diffuse shading\n"
2546 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2547 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2549 "#ifdef USESPECULAR\n"
2550 " // calculate directional shading\n"
2551 " float3 eyevector = position * -1.0;\n"
2552 "# ifdef USEEXACTSPECULARMATH\n"
2553 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2555 " half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2556 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2560 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2561 " fade *= ShadowMapCompare(CubeVector,\n"
2562 "# if defined(USESHADOWMAP2D)\n"
2563 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2565 "# if defined(USESHADOWMAPRECT)\n"
2566 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2568 "# if defined(USESHADOWMAPCUBE)\n"
2569 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2572 "#ifdef USESHADOWMAPVSDCT\n"
2573 ", Texture_CubeProjection\n"
2578 "#ifdef USEDIFFUSE\n"
2579 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2581 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2583 "#ifdef USESPECULAR\n"
2584 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2586 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2589 "# ifdef USECUBEFILTER\n"
2590 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2591 " gl_FragData0 *= cubecolor;\n"
2592 " gl_FragData1 *= cubecolor;\n"
2595 "#endif // FRAGMENT_SHADER\n"
2596 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2601 "#ifdef VERTEX_SHADER\n"
2604 "float4 gl_Vertex : POSITION,\n"
2605 "uniform float4x4 ModelViewProjectionMatrix,\n"
2606 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2607 "float4 gl_Color : COLOR0,\n"
2609 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2610 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2611 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2612 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2613 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2615 "uniform float3 EyePosition,\n"
2616 "uniform mat4 TexMatrix,\n"
2617 "#ifdef USEVERTEXTEXTUREBLEND\n"
2618 "uniform mat4 BackgroundTexMatrix,\n"
2620 "#ifdef MODE_LIGHTSOURCE\n"
2621 "uniform mat4 ModelToLight,\n"
2623 "#ifdef MODE_LIGHTSOURCE\n"
2624 "uniform float3 LightPosition,\n"
2626 "#ifdef MODE_LIGHTDIRECTION\n"
2627 "uniform float3 LightDir,\n"
2629 "uniform float4 FogPlane,\n"
2630 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2631 "uniform float3 LightPosition,\n"
2634 "out float4 gl_FrontColor : COLOR,\n"
2635 "out float4 TexCoordBoth : TEXCOORD0,\n"
2636 "#ifdef USELIGHTMAP\n"
2637 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2639 "#ifdef USEEYEVECTOR\n"
2640 "out float3 EyeVector : TEXCOORD2,\n"
2642 "#ifdef USEREFLECTION\n"
2643 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2646 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2648 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2649 "out float3 LightVector : TEXCOORD5,\n"
2651 "#ifdef MODE_LIGHTSOURCE\n"
2652 "out float3 CubeVector : TEXCOORD3,\n"
2654 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2655 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2656 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2657 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2659 "out float4 gl_Position : POSITION\n"
2662 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2663 " gl_FrontColor = gl_Color;\n"
2665 " // copy the surface texcoord\n"
2666 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2667 "#ifdef USEVERTEXTEXTUREBLEND\n"
2668 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2670 "#ifdef USELIGHTMAP\n"
2671 " TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2674 "#ifdef MODE_LIGHTSOURCE\n"
2675 " // transform vertex position into light attenuation/cubemap space\n"
2676 " // (-1 to +1 across the light box)\n"
2677 " CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2679 "# ifdef USEDIFFUSE\n"
2680 " // transform unnormalized light direction into tangent space\n"
2681 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2682 " // normalize it per pixel)\n"
2683 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2684 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2685 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2686 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2690 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2691 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2692 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2693 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2696 " // transform unnormalized eye direction into tangent space\n"
2697 "#ifdef USEEYEVECTOR\n"
2698 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2699 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2700 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2701 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2705 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2706 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2709 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2710 " VectorS = gl_MultiTexCoord1.xyz;\n"
2711 " VectorT = gl_MultiTexCoord2.xyz;\n"
2712 " VectorR = gl_MultiTexCoord3.xyz;\n"
2715 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2716 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2718 "#ifdef USEREFLECTION\n"
2719 " ModelViewProjectionPosition = gl_Position;\n"
2722 "#endif // VERTEX_SHADER\n"
2727 "#ifdef FRAGMENT_SHADER\n"
2730 "#ifdef USEDEFERREDLIGHTMAP\n"
2731 "float2 Pixel : WPOS,\n"
2733 "float4 gl_FrontColor : COLOR,\n"
2734 "float4 TexCoordBoth : TEXCOORD0,\n"
2735 "#ifdef USELIGHTMAP\n"
2736 "float2 TexCoordLightmap : TEXCOORD1,\n"
2738 "#ifdef USEEYEVECTOR\n"
2739 "float3 EyeVector : TEXCOORD2,\n"
2741 "#ifdef USEREFLECTION\n"
2742 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2745 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2747 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2748 "float3 LightVector : TEXCOORD5,\n"
2750 "#ifdef MODE_LIGHTSOURCE\n"
2751 "float3 CubeVector : TEXCOORD3,\n"
2753 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2754 "float4 ModelViewPosition : TEXCOORD0,\n"
2756 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2757 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2758 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2759 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2762 "uniform sampler2D Texture_Normal,\n"
2763 "uniform sampler2D Texture_Color,\n"
2764 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2765 "uniform sampler2D Texture_Gloss,\n"
2768 "uniform sampler2D Texture_Glow,\n"
2770 "#ifdef USEVERTEXTEXTUREBLEND\n"
2771 "uniform sampler2D Texture_SecondaryNormal,\n"
2772 "uniform sampler2D Texture_SecondaryColor,\n"
2773 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2774 "uniform sampler2D Texture_SecondaryGloss,\n"
2777 "uniform sampler2D Texture_SecondaryGlow,\n"
2780 "#ifdef USECOLORMAPPING\n"
2781 "uniform sampler2D Texture_Pants,\n"
2782 "uniform sampler2D Texture_Shirt,\n"
2785 "uniform sampler2D Texture_FogMask,\n"
2787 "#ifdef USELIGHTMAP\n"
2788 "uniform sampler2D Texture_Lightmap,\n"
2790 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2791 "uniform sampler2D Texture_Deluxemap,\n"
2793 "#ifdef USEREFLECTION\n"
2794 "uniform sampler2D Texture_Reflection,\n"
2797 "//#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2798 "uniform samplerRECT Texture_ScreenDepth,\n"
2799 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2801 "#ifdef USEDEFERREDLIGHTMAP\n"
2802 "uniform samplerRECT Texture_ScreenDiffuse,\n"
2803 "uniform samplerRECT Texture_ScreenSpecular,\n"
2806 "#ifdef USECOLORMAPPING\n"
2807 "uniform half3 Color_Pants,\n"
2808 "uniform half3 Color_Shirt,\n"
2811 "uniform float3 FogColor,\n"
2812 "uniform float FogRangeRecip,\n"
2813 "uniform float FogPlaneViewDist,\n"
2814 "uniform float FogHeightFade,\n"
2817 "#ifdef USEOFFSETMAPPING\n"
2818 "uniform float OffsetMapping_Scale,\n"
2821 "#ifdef USEDEFERREDLIGHTMAP\n"
2822 "uniform half3 DeferredMod_Diffuse,\n"
2823 "uniform half3 DeferredMod_Specular,\n"
2825 "uniform half3 Color_Ambient,\n"
2826 "uniform half3 Color_Diffuse,\n"
2827 "uniform half3 Color_Specular,\n"
2828 "uniform half SpecularPower,\n"
2830 "uniform half3 Color_Glow,\n"
2832 "uniform half Alpha,\n"
2833 "#ifdef USEREFLECTION\n"
2834 "uniform float4 DistortScaleRefractReflect,\n"
2835 "uniform float4 ScreenScaleRefractReflect,\n"
2836 "uniform float4 ScreenCenterRefractReflect,\n"
2837 "uniform half4 ReflectColor,\n"
2839 "#ifdef MODE_LIGHTDIRECTION\n"
2840 "uniform half3 LightColor,\n"
2842 "#ifdef MODE_LIGHTSOURCE\n"
2843 "uniform half3 LightColor,\n"
2846 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2847 "uniform sampler2D Texture_Attenuation,\n"
2848 "uniform samplerCUBE Texture_Cube,\n"
2850 "#ifdef USESHADOWMAPRECT\n"
2851 "# ifdef USESHADOWSAMPLER\n"
2852 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2854 "uniform samplerRECT Texture_ShadowMapRect,\n"
2858 "#ifdef USESHADOWMAP2D\n"
2859 "# ifdef USESHADOWSAMPLER\n"
2860 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2862 "uniform sampler2D Texture_ShadowMap2D,\n"
2866 "#ifdef USESHADOWMAPVSDCT\n"
2867 "uniform samplerCUBE Texture_CubeProjection,\n"
2870 "#ifdef USESHADOWMAPCUBE\n"
2871 "# ifdef USESHADOWSAMPLER\n"
2872 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2874 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2878 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2879 "uniform float2 ShadowMap_TextureScale,\n"
2880 "uniform float4 ShadowMap_Parameters,\n"
2882 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2884 "out float4 gl_FragColor : COLOR\n"
2887 " float2 TexCoord = TexCoordBoth.xy;\n"
2888 "#ifdef USEVERTEXTEXTUREBLEND\n"
2889 " float2 TexCoord2 = TexCoordBoth.zw;\n"
2891 "#ifdef USEOFFSETMAPPING\n"
2892 " // apply offsetmapping\n"
2893 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2894 "#define TexCoord TexCoordOffset\n"
2897 " // combine the diffuse textures (base, pants, shirt)\n"
2898 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2899 "#ifdef USEALPHAKILL\n"
2900 " if (color.a < 0.5)\n"
2903 " color.a *= Alpha;\n"
2904 "#ifdef USECOLORMAPPING\n"
2905 " color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2907 "#ifdef USEVERTEXTEXTUREBLEND\n"
2908 " float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2909 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2910 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2911 " color.rgb = half3(mix(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2913 " //color = mix(half4(1, 0, 0, 1), color, terrainblend);\n"
2916 " // get the surface normal\n"
2917 "#ifdef USEVERTEXTEXTUREBLEND\n"
2918 " half3 surfacenormal = normalize(half3(mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2920 " half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2923 " // get the material colors\n"
2924 " half3 diffusetex = color.rgb;\n"
2925 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2926 "# ifdef USEVERTEXTEXTUREBLEND\n"
2927 " half3 glosstex = half3(mix(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2929 " half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2936 "#ifdef MODE_LIGHTSOURCE\n"
2937 " // light source\n"
2938 " half3 lightnormal = half3(normalize(LightVector));\n"
2939 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2940 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2941 "#ifdef USESPECULAR\n"
2942 "#ifdef USEEXACTSPECULARMATH\n"
2943 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2945 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2946 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2948 " color.rgb += glosstex * (specular * Color_Specular);\n"
2950 " color.rgb *= LightColor;\n"
2951 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2952 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2953 " color.rgb *= ShadowMapCompare(CubeVector,\n"
2954 "# if defined(USESHADOWMAP2D)\n"
2955 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2957 "# if defined(USESHADOWMAPRECT)\n"
2958 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2960 "# if defined(USESHADOWMAPCUBE)\n"
2961 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2964 "#ifdef USESHADOWMAPVSDCT\n"
2965 ", Texture_CubeProjection\n"
2970 "# ifdef USECUBEFILTER\n"
2971 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2973 "#endif // MODE_LIGHTSOURCE\n"
2978 "#ifdef MODE_LIGHTDIRECTION\n"
2980 " half3 lightnormal = half3(normalize(LightVector));\n"
2981 "#define lightcolor LightColor\n"
2982 "#endif // MODE_LIGHTDIRECTION\n"
2983 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2985 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
2986 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
2987 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
2988 " // convert modelspace light vector to tangentspace\n"
2989 " half3 lightnormal;\n"
2990 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
2991 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
2992 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
2993 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
2994 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
2995 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
2996 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
2997 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
2998 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
2999 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3000 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3001 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3002 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3003 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3004 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3006 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3007 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3008 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3014 "#ifdef MODE_LIGHTMAP\n"
3015 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3016 "#endif // MODE_LIGHTMAP\n"
3017 "#ifdef MODE_VERTEXCOLOR\n"
3018 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3019 "#endif // MODE_VERTEXCOLOR\n"
3020 "#ifdef MODE_FLATCOLOR\n"
3021 " color.rgb = diffusetex * Color_Ambient;\n"
3022 "#endif // MODE_FLATCOLOR\n"
3028 "# ifdef USEDIFFUSE\n"
3029 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3030 "# ifdef USESPECULAR\n"
3031 "# ifdef USEEXACTSPECULARMATH\n"
3032 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3034 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3035 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3037 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3039 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3042 " color.rgb = diffusetex * Color_Ambient;\n"
3046 "#ifdef USEDEFERREDLIGHTMAP\n"
3047 " color.rgb += diffusetex * half3(texRECT(Texture_ScreenDiffuse, Pixel)) * DeferredMod_Diffuse;\n"
3048 " color.rgb += glosstex * half3(texRECT(Texture_ScreenSpecular, Pixel)) * DeferredMod_Specular;\n"
3049 " color.rgb = half3(texRECT(Texture_ScreenDepth, Pixel));\n"
3053 "#ifdef USEVERTEXTEXTUREBLEND\n"
3054 " color.rgb += mix(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3056 " color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3061 "#ifdef MODE_LIGHTSOURCE\n"
3062 " color.rgb *= half(FogVertex());\n"
3064 " color.rgb = mix(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3068 " // 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"
3069 "#ifdef USEREFLECTION\n"
3070 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3071 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3072 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3073 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3074 " // FIXME temporary hack to detect the case that the reflection\n"
3075 " // gets blackened at edges due to leaving the area that contains actual\n"
3077 " // Remove this 'ack once we have a better way to stop this thing from\n"
3079 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3080 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3081 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3082 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3083 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3084 " color.rgb = mix(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3087 " gl_FragColor = float4(color);\n"
3089 "#endif // FRAGMENT_SHADER\n"
3091 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3092 "#endif // !MODE_DEFERREDGEOMETRY\n"
3093 "#endif // !MODE_WATER\n"
3094 "#endif // !MODE_REFRACTION\n"
3095 "#endif // !MODE_BLOOMBLUR\n"
3096 "#endif // !MODE_GENERIC\n"
3097 "#endif // !MODE_POSTPROCESS\n"
3098 "#endif // !MODE_SHOWDEPTH\n"
3099 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3102 //=======================================================================================================================================================
3104 typedef struct shaderpermutationinfo_s
3106 const char *pretext;
3109 shaderpermutationinfo_t;
3111 typedef struct shadermodeinfo_s
3113 const char *vertexfilename;
3114 const char *geometryfilename;
3115 const char *fragmentfilename;
3116 const char *pretext;
3121 typedef enum shaderpermutation_e
3123 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3124 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3125 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3126 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3127 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3128 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3129 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3130 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3131 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3132 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3133 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3134 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3135 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3136 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3137 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3138 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3139 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3140 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3141 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3142 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3143 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3144 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3145 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3146 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3147 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3148 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3149 SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3150 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3152 shaderpermutation_t;
3154 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3155 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3157 {"#define USEDIFFUSE\n", " diffuse"},
3158 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3159 {"#define USEVIEWTINT\n", " viewtint"},
3160 {"#define USECOLORMAPPING\n", " colormapping"},
3161 {"#define USESATURATION\n", " saturation"},
3162 {"#define USEFOGINSIDE\n", " foginside"},
3163 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3164 {"#define USEGAMMARAMPS\n", " gammaramps"},
3165 {"#define USECUBEFILTER\n", " cubefilter"},
3166 {"#define USEGLOW\n", " glow"},
3167 {"#define USEBLOOM\n", " bloom"},
3168 {"#define USESPECULAR\n", " specular"},
3169 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3170 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3171 {"#define USEREFLECTION\n", " reflection"},
3172 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3173 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3174 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3175 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3176 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3177 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3178 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3179 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3180 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3181 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3182 {"#define USEALPHAKILL\n", " alphakill"},
3185 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3186 typedef enum shadermode_e
3188 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3189 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3190 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3191 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3192 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3193 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3194 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3195 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3196 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3197 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3198 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3199 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3200 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3201 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3202 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3207 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3208 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3210 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3211 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3212 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3213 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3214 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3215 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3216 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3217 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3218 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3219 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3220 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3221 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3222 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3223 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3224 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3228 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3230 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3231 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3232 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3233 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3234 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3235 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3236 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3237 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3238 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3239 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3240 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3241 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3242 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3243 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3244 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3248 struct r_glsl_permutation_s;
3249 typedef struct r_glsl_permutation_s
3251 /// hash lookup data
3252 struct r_glsl_permutation_s *hashnext;
3254 unsigned int permutation;
3256 /// indicates if we have tried compiling this permutation already
3258 /// 0 if compilation failed
3260 /// locations of detected uniforms in program object, or -1 if not found
3261 int loc_Texture_First;
3262 int loc_Texture_Second;
3263 int loc_Texture_GammaRamps;
3264 int loc_Texture_Normal;
3265 int loc_Texture_Color;
3266 int loc_Texture_Gloss;
3267 int loc_Texture_Glow;
3268 int loc_Texture_SecondaryNormal;
3269 int loc_Texture_SecondaryColor;
3270 int loc_Texture_SecondaryGloss;
3271 int loc_Texture_SecondaryGlow;
3272 int loc_Texture_Pants;
3273 int loc_Texture_Shirt;
3274 int loc_Texture_FogMask;
3275 int loc_Texture_Lightmap;
3276 int loc_Texture_Deluxemap;
3277 int loc_Texture_Attenuation;
3278 int loc_Texture_Cube;
3279 int loc_Texture_Refraction;
3280 int loc_Texture_Reflection;
3281 int loc_Texture_ShadowMapRect;
3282 int loc_Texture_ShadowMapCube;
3283 int loc_Texture_ShadowMap2D;
3284 int loc_Texture_CubeProjection;
3285 int loc_Texture_ScreenDepth;
3286 int loc_Texture_ScreenNormalMap;
3287 int loc_Texture_ScreenDiffuse;
3288 int loc_Texture_ScreenSpecular;
3290 int loc_BloomBlur_Parameters;
3292 int loc_Color_Ambient;
3293 int loc_Color_Diffuse;
3294 int loc_Color_Specular;
3296 int loc_Color_Pants;
3297 int loc_Color_Shirt;
3298 int loc_DeferredColor_Ambient;
3299 int loc_DeferredColor_Diffuse;
3300 int loc_DeferredColor_Specular;
3301 int loc_DeferredMod_Diffuse;
3302 int loc_DeferredMod_Specular;
3303 int loc_DistortScaleRefractReflect;
3304 int loc_EyePosition;
3306 int loc_FogHeightFade;
3308 int loc_FogPlaneViewDist;
3309 int loc_FogRangeRecip;
3312 int loc_LightPosition;
3313 int loc_OffsetMapping_Scale;
3315 int loc_ReflectColor;
3316 int loc_ReflectFactor;
3317 int loc_ReflectOffset;
3318 int loc_RefractColor;
3320 int loc_ScreenCenterRefractReflect;
3321 int loc_ScreenScaleRefractReflect;
3322 int loc_ScreenToDepth;
3323 int loc_ShadowMap_Parameters;
3324 int loc_ShadowMap_TextureScale;
3325 int loc_SpecularPower;
3330 int loc_ViewTintColor;
3331 int loc_ViewToLight;
3332 int loc_ModelToLight;
3334 int loc_BackgroundTexMatrix;
3335 int loc_ModelViewProjectionMatrix;
3336 int loc_ModelViewMatrix;
3338 r_glsl_permutation_t;
3340 #define SHADERPERMUTATION_HASHSIZE 256
3342 /// information about each possible shader permutation
3343 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3344 /// currently selected permutation
3345 r_glsl_permutation_t *r_glsl_permutation;
3346 /// storage for permutations linked in the hash table
3347 memexpandablearray_t r_glsl_permutationarray;
3349 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3351 //unsigned int hashdepth = 0;
3352 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3353 r_glsl_permutation_t *p;
3354 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3356 if (p->mode == mode && p->permutation == permutation)
3358 //if (hashdepth > 10)
3359 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3364 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3366 p->permutation = permutation;
3367 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3368 r_glsl_permutationhash[mode][hashindex] = p;
3369 //if (hashdepth > 10)
3370 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3374 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3377 if (!filename || !filename[0])
3379 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3382 if (printfromdisknotice)
3383 Con_DPrintf("from disk %s... ", filename);
3384 return shaderstring;
3386 else if (!strcmp(filename, "glsl/default.glsl"))
3388 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3389 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3391 return shaderstring;
3394 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3397 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3398 int vertstrings_count = 0;
3399 int geomstrings_count = 0;
3400 int fragstrings_count = 0;
3401 char *vertexstring, *geometrystring, *fragmentstring;
3402 const char *vertstrings_list[32+3];
3403 const char *geomstrings_list[32+3];
3404 const char *fragstrings_list[32+3];
3405 char permutationname[256];
3412 permutationname[0] = 0;
3413 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3414 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3415 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3417 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3419 // the first pretext is which type of shader to compile as
3420 // (later these will all be bound together as a program object)
3421 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3422 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3423 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3425 // the second pretext is the mode (for example a light source)
3426 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3427 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3428 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3429 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3431 // now add all the permutation pretexts
3432 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3434 if (permutation & (1<<i))
3436 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3437 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3438 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3439 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3443 // keep line numbers correct
3444 vertstrings_list[vertstrings_count++] = "\n";
3445 geomstrings_list[geomstrings_count++] = "\n";
3446 fragstrings_list[fragstrings_count++] = "\n";
3450 // now append the shader text itself
3451 vertstrings_list[vertstrings_count++] = vertexstring;
3452 geomstrings_list[geomstrings_count++] = geometrystring;
3453 fragstrings_list[fragstrings_count++] = fragmentstring;
3455 // if any sources were NULL, clear the respective list
3457 vertstrings_count = 0;
3458 if (!geometrystring)
3459 geomstrings_count = 0;
3460 if (!fragmentstring)
3461 fragstrings_count = 0;
3463 // compile the shader program
3464 if (vertstrings_count + geomstrings_count + fragstrings_count)
3465 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3469 qglUseProgramObjectARB(p->program);CHECKGLERROR
3470 // look up all the uniform variable names we care about, so we don't
3471 // have to look them up every time we set them
3473 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3474 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3475 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3476 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3477 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3478 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3479 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3480 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3481 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3482 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3483 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3484 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3485 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3486 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3487 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3488 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3489 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3490 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3491 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3492 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3493 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3494 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3495 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3496 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3497 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3498 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3499 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3500 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3501 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3502 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3503 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3504 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3505 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3506 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3507 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3508 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3509 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3510 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3511 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3512 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3513 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3514 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3515 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3516 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3517 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3518 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3519 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3520 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3521 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3522 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3523 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3524 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3525 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3526 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3527 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3528 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3529 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3530 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3531 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3532 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3533 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3534 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3535 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3536 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3537 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3538 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3539 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3540 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3541 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3542 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3543 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3544 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3545 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3546 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3547 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3548 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3549 // initialize the samplers to refer to the texture units we use
3550 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3551 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3552 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3553 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3554 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3555 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3556 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3557 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3558 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3559 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3560 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3561 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3562 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3563 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3564 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3565 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3566 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3567 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3568 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3569 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3570 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
3571 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
3572 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3573 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3574 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3575 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3576 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3577 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3579 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3582 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3586 Mem_Free(vertexstring);
3588 Mem_Free(geometrystring);
3590 Mem_Free(fragmentstring);
3593 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3595 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3596 if (r_glsl_permutation != perm)
3598 r_glsl_permutation = perm;
3599 if (!r_glsl_permutation->program)
3601 if (!r_glsl_permutation->compiled)
3602 R_GLSL_CompilePermutation(perm, mode, permutation);
3603 if (!r_glsl_permutation->program)
3605 // remove features until we find a valid permutation
3607 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3609 // reduce i more quickly whenever it would not remove any bits
3610 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3611 if (!(permutation & j))
3614 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3615 if (!r_glsl_permutation->compiled)
3616 R_GLSL_CompilePermutation(perm, mode, permutation);
3617 if (r_glsl_permutation->program)
3620 if (i >= SHADERPERMUTATION_COUNT)
3622 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3623 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3624 qglUseProgramObjectARB(0);CHECKGLERROR
3625 return; // no bit left to clear, entire mode is broken
3630 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3632 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3636 #include <Cg/cgGL.h>
3637 struct r_cg_permutation_s;
3638 typedef struct r_cg_permutation_s
3640 /// hash lookup data
3641 struct r_cg_permutation_s *hashnext;
3643 unsigned int permutation;
3645 /// indicates if we have tried compiling this permutation already
3647 /// 0 if compilation failed
3650 /// locations of detected parameters in programs, or NULL if not found
3651 CGparameter vp_EyePosition;
3652 CGparameter vp_FogPlane;
3653 CGparameter vp_LightDir;
3654 CGparameter vp_LightPosition;
3655 CGparameter vp_ModelToLight;
3656 CGparameter vp_TexMatrix;
3657 CGparameter vp_BackgroundTexMatrix;
3658 CGparameter vp_ModelViewProjectionMatrix;
3659 CGparameter vp_ModelViewMatrix;
3661 CGparameter fp_Texture_First;
3662 CGparameter fp_Texture_Second;
3663 CGparameter fp_Texture_GammaRamps;
3664 CGparameter fp_Texture_Normal;
3665 CGparameter fp_Texture_Color;
3666 CGparameter fp_Texture_Gloss;
3667 CGparameter fp_Texture_Glow;
3668 CGparameter fp_Texture_SecondaryNormal;
3669 CGparameter fp_Texture_SecondaryColor;
3670 CGparameter fp_Texture_SecondaryGloss;
3671 CGparameter fp_Texture_SecondaryGlow;
3672 CGparameter fp_Texture_Pants;
3673 CGparameter fp_Texture_Shirt;
3674 CGparameter fp_Texture_FogMask;
3675 CGparameter fp_Texture_Lightmap;
3676 CGparameter fp_Texture_Deluxemap;
3677 CGparameter fp_Texture_Attenuation;
3678 CGparameter fp_Texture_Cube;
3679 CGparameter fp_Texture_Refraction;
3680 CGparameter fp_Texture_Reflection;
3681 CGparameter fp_Texture_ShadowMapRect;
3682 CGparameter fp_Texture_ShadowMapCube;
3683 CGparameter fp_Texture_ShadowMap2D;
3684 CGparameter fp_Texture_CubeProjection;
3685 CGparameter fp_Texture_ScreenDepth;
3686 CGparameter fp_Texture_ScreenNormalMap;
3687 CGparameter fp_Texture_ScreenDiffuse;
3688 CGparameter fp_Texture_ScreenSpecular;
3689 CGparameter fp_Alpha;
3690 CGparameter fp_BloomBlur_Parameters;
3691 CGparameter fp_ClientTime;
3692 CGparameter fp_Color_Ambient;
3693 CGparameter fp_Color_Diffuse;
3694 CGparameter fp_Color_Specular;
3695 CGparameter fp_Color_Glow;
3696 CGparameter fp_Color_Pants;
3697 CGparameter fp_Color_Shirt;
3698 CGparameter fp_DeferredColor_Ambient;
3699 CGparameter fp_DeferredColor_Diffuse;
3700 CGparameter fp_DeferredColor_Specular;
3701 CGparameter fp_DeferredMod_Diffuse;
3702 CGparameter fp_DeferredMod_Specular;
3703 CGparameter fp_DistortScaleRefractReflect;
3704 CGparameter fp_EyePosition;
3705 CGparameter fp_FogColor;
3706 CGparameter fp_FogHeightFade;
3707 CGparameter fp_FogPlane;
3708 CGparameter fp_FogPlaneViewDist;
3709 CGparameter fp_FogRangeRecip;
3710 CGparameter fp_LightColor;
3711 CGparameter fp_LightDir;
3712 CGparameter fp_LightPosition;
3713 CGparameter fp_OffsetMapping_Scale;
3714 CGparameter fp_PixelSize;
3715 CGparameter fp_ReflectColor;
3716 CGparameter fp_ReflectFactor;
3717 CGparameter fp_ReflectOffset;
3718 CGparameter fp_RefractColor;
3719 CGparameter fp_Saturation;
3720 CGparameter fp_ScreenCenterRefractReflect;
3721 CGparameter fp_ScreenScaleRefractReflect;
3722 CGparameter fp_ScreenToDepth;
3723 CGparameter fp_ShadowMap_Parameters;
3724 CGparameter fp_ShadowMap_TextureScale;
3725 CGparameter fp_SpecularPower;
3726 CGparameter fp_UserVec1;
3727 CGparameter fp_UserVec2;
3728 CGparameter fp_UserVec3;
3729 CGparameter fp_UserVec4;
3730 CGparameter fp_ViewTintColor;
3731 CGparameter fp_ViewToLight;
3735 /// information about each possible shader permutation
3736 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3737 /// currently selected permutation
3738 r_cg_permutation_t *r_cg_permutation;
3739 /// storage for permutations linked in the hash table
3740 memexpandablearray_t r_cg_permutationarray;
3742 #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));}}
3744 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3746 //unsigned int hashdepth = 0;
3747 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3748 r_cg_permutation_t *p;
3749 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3751 if (p->mode == mode && p->permutation == permutation)
3753 //if (hashdepth > 10)
3754 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3759 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3761 p->permutation = permutation;
3762 p->hashnext = r_cg_permutationhash[mode][hashindex];
3763 r_cg_permutationhash[mode][hashindex] = p;
3764 //if (hashdepth > 10)
3765 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3769 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3772 if (!filename || !filename[0])
3774 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3777 if (printfromdisknotice)
3778 Con_DPrintf("from disk %s... ", filename);
3779 return shaderstring;
3781 else if (!strcmp(filename, "cg/default.cg"))
3783 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3784 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3786 return shaderstring;
3789 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3792 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3793 int vertstrings_count = 0, vertstring_length = 0;
3794 int geomstrings_count = 0, geomstring_length = 0;
3795 int fragstrings_count = 0, fragstring_length = 0;
3797 char *vertexstring, *geometrystring, *fragmentstring;
3798 char *vertstring, *geomstring, *fragstring;
3799 const char *vertstrings_list[32+3];
3800 const char *geomstrings_list[32+3];
3801 const char *fragstrings_list[32+3];
3802 char permutationname[256];
3803 CGprofile vertexProfile;
3804 CGprofile fragmentProfile;
3812 permutationname[0] = 0;
3813 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
3814 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3815 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3817 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3819 // the first pretext is which type of shader to compile as
3820 // (later these will all be bound together as a program object)
3821 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3822 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3823 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3825 // the second pretext is the mode (for example a light source)
3826 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3827 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3828 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3829 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3831 // now add all the permutation pretexts
3832 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3834 if (permutation & (1<<i))
3836 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3837 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3838 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3839 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3843 // keep line numbers correct
3844 vertstrings_list[vertstrings_count++] = "\n";
3845 geomstrings_list[geomstrings_count++] = "\n";
3846 fragstrings_list[fragstrings_count++] = "\n";
3850 // now append the shader text itself
3851 vertstrings_list[vertstrings_count++] = vertexstring;
3852 geomstrings_list[geomstrings_count++] = geometrystring;
3853 fragstrings_list[fragstrings_count++] = fragmentstring;
3855 // if any sources were NULL, clear the respective list
3857 vertstrings_count = 0;
3858 if (!geometrystring)
3859 geomstrings_count = 0;
3860 if (!fragmentstring)
3861 fragstrings_count = 0;
3863 vertstring_length = 0;
3864 for (i = 0;i < vertstrings_count;i++)
3865 vertstring_length += strlen(vertstrings_list[i]);
3866 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3867 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3868 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3870 geomstring_length = 0;
3871 for (i = 0;i < geomstrings_count;i++)
3872 geomstring_length += strlen(geomstrings_list[i]);
3873 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3874 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3875 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3877 fragstring_length = 0;
3878 for (i = 0;i < fragstrings_count;i++)
3879 fragstring_length += strlen(fragstrings_list[i]);
3880 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3881 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3882 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3886 //vertexProfile = CG_PROFILE_ARBVP1;
3887 //fragmentProfile = CG_PROFILE_ARBFP1;
3888 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3889 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3890 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3891 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3892 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3895 // compile the vertex program
3896 if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL)))
3899 cgCompileProgram(p->vprogram);CHECKCGERROR
3900 if (!cgIsProgramCompiled(p->vprogram))
3903 cgDestroyProgram(p->vprogram);CHECKCGERROR
3908 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3909 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3910 // look up all the uniform variable names we care about, so we don't
3911 // have to look them up every time we set them
3913 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
3914 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
3915 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
3916 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
3917 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
3918 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
3919 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3920 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3921 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3926 // compile the fragment program
3927 if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL)))
3929 cgCompileProgram(p->fprogram);CHECKCGERROR
3930 if (!cgIsProgramCompiled(p->fprogram))
3933 cgDestroyProgram(p->fprogram);CHECKCGERROR
3938 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3939 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3941 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
3942 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
3943 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3944 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3945 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
3946 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3947 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3948 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3949 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3950 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3951 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3952 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3953 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3954 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3955 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3956 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3957 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3958 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3959 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3960 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3961 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3962 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3963 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3964 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3965 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3966 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3967 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3968 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3969 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
3970 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3971 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
3972 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
3973 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
3974 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
3975 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
3976 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
3977 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
3978 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
3979 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
3980 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
3981 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
3982 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
3983 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
3984 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
3985 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
3986 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
3987 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
3988 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
3989 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
3990 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
3991 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
3992 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
3993 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
3994 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
3995 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
3996 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
3997 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
3998 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
3999 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4000 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4001 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4002 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4003 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4004 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4005 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4006 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4007 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4008 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4009 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4010 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4011 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4016 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4017 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4019 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4023 Mem_Free(vertstring);
4025 Mem_Free(geomstring);
4027 Mem_Free(fragstring);
4029 Mem_Free(vertexstring);
4031 Mem_Free(geometrystring);
4033 Mem_Free(fragmentstring);
4036 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4038 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4041 if (r_cg_permutation != perm)
4043 r_cg_permutation = perm;
4044 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4046 if (!r_cg_permutation->compiled)
4047 R_CG_CompilePermutation(perm, mode, permutation);
4048 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4050 // remove features until we find a valid permutation
4052 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4054 // reduce i more quickly whenever it would not remove any bits
4055 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4056 if (!(permutation & j))
4059 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4060 if (!r_cg_permutation->compiled)
4061 R_CG_CompilePermutation(perm, mode, permutation);
4062 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4065 if (i >= SHADERPERMUTATION_COUNT)
4067 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4068 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4069 return; // no bit left to clear, entire mode is broken
4075 if (r_cg_permutation->vprogram)
4077 //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4078 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4079 //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4083 //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4084 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4086 if (r_cg_permutation->fprogram)
4088 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4089 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4090 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4094 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4095 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4099 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4102 void CG_BindTexture(CGparameter param, int texnum)
4104 cgGLSetTextureParameter(param, texnum);
4105 cgGLEnableTextureParameter(param);
4109 void R_GLSL_Restart_f(void)
4111 unsigned int i, limit;
4112 switch(vid.renderpath)
4114 case RENDERPATH_GL20:
4116 r_glsl_permutation_t *p;
4117 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4118 for (i = 0;i < limit;i++)
4120 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4122 GL_Backend_FreeProgram(p->program);
4123 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4126 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4129 case RENDERPATH_CGGL:
4132 r_cg_permutation_t *p;
4133 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4134 for (i = 0;i < limit;i++)
4136 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4139 cgDestroyProgram(p->vprogram);
4141 cgDestroyProgram(p->fprogram);
4142 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4146 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4149 case RENDERPATH_GL13:
4150 case RENDERPATH_GL11:
4155 void R_GLSL_DumpShader_f(void)
4160 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4163 FS_Print(file, "/* The engine may define the following macros:\n");
4164 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4165 for (i = 0;i < SHADERMODE_COUNT;i++)
4166 FS_Print(file, glslshadermodeinfo[i].pretext);
4167 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4168 FS_Print(file, shaderpermutationinfo[i].pretext);
4169 FS_Print(file, "*/\n");
4170 FS_Print(file, builtinshaderstring);
4172 Con_Printf("glsl/default.glsl written\n");
4175 Con_Printf("failed to write to glsl/default.glsl\n");
4178 file = FS_OpenRealFile("cg/default.cg", "w", false);
4181 FS_Print(file, "/* The engine may define the following macros:\n");
4182 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4183 for (i = 0;i < SHADERMODE_COUNT;i++)
4184 FS_Print(file, cgshadermodeinfo[i].pretext);
4185 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4186 FS_Print(file, shaderpermutationinfo[i].pretext);
4187 FS_Print(file, "*/\n");
4188 FS_Print(file, builtincgshaderstring);
4190 Con_Printf("cg/default.cg written\n");
4193 Con_Printf("failed to write to cg/default.cg\n");
4197 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4200 texturemode = GL_MODULATE;
4201 switch (vid.renderpath)
4203 case RENDERPATH_GL20:
4204 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))));
4205 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4206 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4208 case RENDERPATH_CGGL:
4211 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))));
4212 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4213 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4216 case RENDERPATH_GL13:
4217 R_Mesh_TexBind(0, first );
4218 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4219 R_Mesh_TexBind(1, second);
4221 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4223 case RENDERPATH_GL11:
4224 R_Mesh_TexBind(0, first );
4229 void R_SetupShader_DepthOrShadow(void)
4231 switch (vid.renderpath)
4233 case RENDERPATH_GL20:
4234 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4236 case RENDERPATH_CGGL:
4238 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4241 case RENDERPATH_GL13:
4242 R_Mesh_TexBind(0, 0);
4243 R_Mesh_TexBind(1, 0);
4245 case RENDERPATH_GL11:
4246 R_Mesh_TexBind(0, 0);
4251 void R_SetupShader_ShowDepth(void)
4253 switch (vid.renderpath)
4255 case RENDERPATH_GL20:
4256 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4258 case RENDERPATH_CGGL:
4260 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4263 case RENDERPATH_GL13:
4265 case RENDERPATH_GL11:
4270 extern qboolean r_shadow_usingdeferredprepass;
4271 extern cvar_t r_shadow_deferred_8bitrange;
4272 extern rtexture_t *r_shadow_attenuationgradienttexture;
4273 extern rtexture_t *r_shadow_attenuation2dtexture;
4274 extern rtexture_t *r_shadow_attenuation3dtexture;
4275 extern qboolean r_shadow_usingshadowmaprect;
4276 extern qboolean r_shadow_usingshadowmapcube;
4277 extern qboolean r_shadow_usingshadowmap2d;
4278 extern float r_shadow_shadowmap_texturescale[2];
4279 extern float r_shadow_shadowmap_parameters[4];
4280 extern qboolean r_shadow_shadowmapvsdct;
4281 extern qboolean r_shadow_shadowmapsampler;
4282 extern int r_shadow_shadowmappcf;
4283 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4284 extern rtexture_t *r_shadow_shadowmap2dtexture;
4285 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4286 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4287 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4288 extern int r_shadow_prepass_width;
4289 extern int r_shadow_prepass_height;
4290 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4291 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4292 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4293 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4294 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4296 // select a permutation of the lighting shader appropriate to this
4297 // combination of texture, entity, light source, and fogging, only use the
4298 // minimum features necessary to avoid wasting rendering time in the
4299 // fragment shader on features that are not being used
4300 unsigned int permutation = 0;
4301 unsigned int mode = 0;
4303 // TODO: implement geometry-shader based shadow volumes someday
4304 if (r_glsl_offsetmapping.integer)
4306 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4307 if (r_glsl_offsetmapping_reliefmapping.integer)
4308 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4310 if (rsurfacepass == RSURFPASS_BACKGROUND)
4312 // distorted background
4313 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4314 mode = SHADERMODE_WATER;
4316 mode = SHADERMODE_REFRACTION;
4318 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4320 // normalmap (deferred prepass), may use alpha test on diffuse
4321 mode = SHADERMODE_DEFERREDGEOMETRY;
4322 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4323 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4324 if (r_glsl_offsetmapping.integer)
4326 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4327 if (r_glsl_offsetmapping_reliefmapping.integer)
4328 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4331 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4334 mode = SHADERMODE_LIGHTSOURCE;
4335 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4336 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4337 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4338 permutation |= SHADERPERMUTATION_CUBEFILTER;
4339 if (diffusescale > 0)
4340 permutation |= SHADERPERMUTATION_DIFFUSE;
4341 if (specularscale > 0)
4342 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4343 if (r_refdef.fogenabled)
4344 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4345 if (rsurface.texture->colormapping)
4346 permutation |= SHADERPERMUTATION_COLORMAPPING;
4347 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4349 if (r_shadow_usingshadowmaprect)
4350 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4351 if (r_shadow_usingshadowmap2d)
4352 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4353 if (r_shadow_usingshadowmapcube)
4354 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4355 else if(r_shadow_shadowmapvsdct)
4356 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4358 if (r_shadow_shadowmapsampler)
4359 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4360 if (r_shadow_shadowmappcf > 1)
4361 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4362 else if (r_shadow_shadowmappcf)
4363 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4366 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4368 // unshaded geometry (fullbright or ambient model lighting)
4369 mode = SHADERMODE_FLATCOLOR;
4370 ambientscale = diffusescale = specularscale = 0;
4371 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4372 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4373 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4374 permutation |= SHADERPERMUTATION_GLOW;
4375 if (r_refdef.fogenabled)
4376 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4377 if (rsurface.texture->colormapping)
4378 permutation |= SHADERPERMUTATION_COLORMAPPING;
4379 if (r_glsl_offsetmapping.integer)
4381 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4382 if (r_glsl_offsetmapping_reliefmapping.integer)
4383 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4385 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4386 permutation |= SHADERPERMUTATION_REFLECTION;
4388 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4390 // directional model lighting
4391 mode = SHADERMODE_LIGHTDIRECTION;
4392 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4393 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4394 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4395 permutation |= SHADERPERMUTATION_GLOW;
4396 permutation |= SHADERPERMUTATION_DIFFUSE;
4397 if (specularscale > 0)
4398 permutation |= SHADERPERMUTATION_SPECULAR;
4399 if (r_refdef.fogenabled)
4400 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4401 if (rsurface.texture->colormapping)
4402 permutation |= SHADERPERMUTATION_COLORMAPPING;
4403 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4404 permutation |= SHADERPERMUTATION_REFLECTION;
4405 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4406 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4408 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4410 // ambient model lighting
4411 mode = SHADERMODE_LIGHTDIRECTION;
4412 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4413 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4414 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4415 permutation |= SHADERPERMUTATION_GLOW;
4416 if (r_refdef.fogenabled)
4417 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4418 if (rsurface.texture->colormapping)
4419 permutation |= SHADERPERMUTATION_COLORMAPPING;
4420 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4421 permutation |= SHADERPERMUTATION_REFLECTION;
4422 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4423 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4428 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4430 // deluxemapping (light direction texture)
4431 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4432 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4434 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4435 permutation |= SHADERPERMUTATION_DIFFUSE;
4436 if (specularscale > 0)
4437 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4439 else if (r_glsl_deluxemapping.integer >= 2)
4441 // fake deluxemapping (uniform light direction in tangentspace)
4442 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4443 permutation |= SHADERPERMUTATION_DIFFUSE;
4444 if (specularscale > 0)
4445 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4447 else if (rsurface.uselightmaptexture)
4449 // ordinary lightmapping (q1bsp, q3bsp)
4450 mode = SHADERMODE_LIGHTMAP;
4454 // ordinary vertex coloring (q3bsp)
4455 mode = SHADERMODE_VERTEXCOLOR;
4457 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4458 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4459 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4460 permutation |= SHADERPERMUTATION_GLOW;
4461 if (r_refdef.fogenabled)
4462 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4463 if (rsurface.texture->colormapping)
4464 permutation |= SHADERPERMUTATION_COLORMAPPING;
4465 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4466 permutation |= SHADERPERMUTATION_REFLECTION;
4467 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4468 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4470 if(permutation & SHADERPERMUTATION_SPECULAR)
4471 if(r_shadow_glossexact.integer)
4472 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4473 if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
4474 permutation |= SHADERPERMUTATION_ALPHAKILL;
4475 switch(vid.renderpath)
4477 case RENDERPATH_GL20:
4478 R_SetupShader_SetPermutationGLSL(mode, permutation);
4479 if (mode == SHADERMODE_LIGHTSOURCE)
4481 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4482 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4483 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4484 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);
4485 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);
4486 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
4488 // additive passes are only darkened by fog, not tinted
4489 if (r_glsl_permutation->loc_FogColor >= 0)
4490 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4491 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]);
4492 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]);
4493 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4497 if (mode == SHADERMODE_FLATCOLOR)
4499 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4501 else if (mode == SHADERMODE_LIGHTDIRECTION)
4503 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]);
4504 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
4505 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);
4506 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);
4507 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);
4508 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]);
4509 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]);
4513 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]);
4514 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]);
4515 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);
4516 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);
4517 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);
4519 // additive passes are only darkened by fog, not tinted
4520 if (r_glsl_permutation->loc_FogColor >= 0)
4522 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4523 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4525 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4527 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);
4528 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]);
4529 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]);
4530 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4531 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4532 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4533 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4534 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4536 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4537 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4538 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4539 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4540 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4541 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4542 if (r_glsl_permutation->loc_Color_Pants >= 0)
4544 if (rsurface.texture->pantstexture)
4545 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4547 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4549 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4551 if (rsurface.texture->shirttexture)
4552 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4554 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4556 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]);
4557 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4558 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4559 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4560 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4561 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]);
4563 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
4564 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
4565 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
4566 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
4567 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
4568 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
4569 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
4570 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
4571 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
4572 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
4573 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
4574 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
4575 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
4576 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
4577 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white );
4578 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_blanknormalmap );
4579 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
4580 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , r_texture_white );
4581 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , r_texture_white );
4582 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
4583 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
4584 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
4585 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
4586 if (rsurface.rtlight)
4588 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
4589 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
4590 if (r_shadow_usingshadowmapcube)
4591 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4592 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
4593 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
4597 case RENDERPATH_CGGL:
4599 R_SetupShader_SetPermutationCG(mode, permutation);
4600 if (mode == SHADERMODE_LIGHTSOURCE)
4602 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4603 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4607 if (mode == SHADERMODE_LIGHTDIRECTION)
4609 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
4612 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
4613 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4614 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4615 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4616 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
4619 if (mode == SHADERMODE_LIGHTSOURCE)
4621 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4622 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4623 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
4624 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
4625 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, specularscale, specularscale, specularscale);CHECKCGERROR
4627 // additive passes are only darkened by fog, not tinted
4628 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4629 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
4630 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
4631 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4635 if (mode == SHADERMODE_FLATCOLOR)
4637 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4639 else if (mode == SHADERMODE_LIGHTDIRECTION)
4641 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
4642 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);CHECKCGERROR
4643 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
4644 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
4645 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
4646 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
4647 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
4651 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
4652 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
4653 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
4654 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
4655 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
4657 // additive passes are only darkened by fog, not tinted
4658 if (r_cg_permutation->fp_FogColor)
4660 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4661 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4663 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4666 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
4667 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
4668 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
4669 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4670 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4671 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4672 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4673 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4675 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4676 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4677 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4678 if (r_cg_permutation->fp_Color_Pants)
4680 if (rsurface.texture->pantstexture)
4681 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4683 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4686 if (r_cg_permutation->fp_Color_Shirt)
4688 if (rsurface.texture->shirttexture)
4689 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4691 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4694 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
4695 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4696 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4697 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4698 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4699 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
4701 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
4702 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
4703 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
4704 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
4705 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
4706 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
4707 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
4708 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
4709 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
4710 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
4711 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
4712 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
4713 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
4714 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
4715 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , r_texture_white );CHECKCGERROR
4716 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , r_texture_blanknormalmap );CHECKCGERROR
4717 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
4718 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , r_texture_white );CHECKCGERROR
4719 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , r_texture_white );CHECKCGERROR
4720 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
4721 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
4722 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
4723 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
4724 if (rsurface.rtlight)
4726 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
4727 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
4728 if (r_shadow_usingshadowmapcube)
4729 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4730 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
4731 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
4737 case RENDERPATH_GL13:
4738 case RENDERPATH_GL11:
4743 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4745 // select a permutation of the lighting shader appropriate to this
4746 // combination of texture, entity, light source, and fogging, only use the
4747 // minimum features necessary to avoid wasting rendering time in the
4748 // fragment shader on features that are not being used
4749 unsigned int permutation = 0;
4750 unsigned int mode = 0;
4751 const float *lightcolorbase = rtlight->currentcolor;
4752 float ambientscale = rtlight->ambientscale;
4753 float diffusescale = rtlight->diffusescale;
4754 float specularscale = rtlight->specularscale;
4755 // this is the location of the light in view space
4756 vec3_t viewlightorigin;
4757 // this transforms from view space (camera) to light space (cubemap)
4758 matrix4x4_t viewtolight;
4759 matrix4x4_t lighttoview;
4760 float viewtolight16f[16];
4761 float range = 1.0f / r_shadow_deferred_8bitrange.value;
4763 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4764 if (rtlight->currentcubemap != r_texture_whitecube)
4765 permutation |= SHADERPERMUTATION_CUBEFILTER;
4766 if (diffusescale > 0)
4767 permutation |= SHADERPERMUTATION_DIFFUSE;
4768 if (specularscale > 0)
4770 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4771 if (r_shadow_glossexact.integer)
4772 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4774 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4776 if (r_shadow_usingshadowmaprect)
4777 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4778 if (r_shadow_usingshadowmap2d)
4779 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4780 if (r_shadow_usingshadowmapcube)
4781 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4782 else if(r_shadow_shadowmapvsdct)
4783 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4785 if (r_shadow_shadowmapsampler)
4786 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4787 if (r_shadow_shadowmappcf > 1)
4788 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4789 else if (r_shadow_shadowmappcf)
4790 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4792 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4793 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4794 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4795 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4796 switch(vid.renderpath)
4798 case RENDERPATH_GL20:
4799 R_SetupShader_SetPermutationGLSL(mode, permutation);
4800 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix , 1, false, gl_modelview16f);
4801 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4802 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
4803 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);
4804 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);
4805 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);
4806 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]);
4807 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]);
4808 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));
4809 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]);
4811 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
4812 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
4813 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
4814 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
4815 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
4816 if (r_shadow_usingshadowmapcube)
4817 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4818 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
4819 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
4821 case RENDERPATH_CGGL:
4823 R_SetupShader_SetPermutationCG(mode, permutation);
4824 if (r_cg_permutation->vp_ModelViewMatrix ) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
4825 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4826 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4827 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
4828 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
4829 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
4830 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
4831 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
4832 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
4833 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
4835 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
4836 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
4837 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
4838 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
4839 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
4840 if (r_shadow_usingshadowmapcube)
4841 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4842 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
4843 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
4846 case RENDERPATH_GL13:
4847 case RENDERPATH_GL11:
4852 #define SKINFRAME_HASH 1024
4856 int loadsequence; // incremented each level change
4857 memexpandablearray_t array;
4858 skinframe_t *hash[SKINFRAME_HASH];
4861 r_skinframe_t r_skinframe;
4863 void R_SkinFrame_PrepareForPurge(void)
4865 r_skinframe.loadsequence++;
4866 // wrap it without hitting zero
4867 if (r_skinframe.loadsequence >= 200)
4868 r_skinframe.loadsequence = 1;
4871 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
4875 // mark the skinframe as used for the purging code
4876 skinframe->loadsequence = r_skinframe.loadsequence;
4879 void R_SkinFrame_Purge(void)
4883 for (i = 0;i < SKINFRAME_HASH;i++)
4885 for (s = r_skinframe.hash[i];s;s = s->next)
4887 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
4889 if (s->merged == s->base)
4891 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
4892 R_PurgeTexture(s->stain );s->stain = NULL;
4893 R_PurgeTexture(s->merged);s->merged = NULL;
4894 R_PurgeTexture(s->base );s->base = NULL;
4895 R_PurgeTexture(s->pants );s->pants = NULL;
4896 R_PurgeTexture(s->shirt );s->shirt = NULL;
4897 R_PurgeTexture(s->nmap );s->nmap = NULL;
4898 R_PurgeTexture(s->gloss );s->gloss = NULL;
4899 R_PurgeTexture(s->glow );s->glow = NULL;
4900 R_PurgeTexture(s->fog );s->fog = NULL;
4901 s->loadsequence = 0;
4907 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
4909 char basename[MAX_QPATH];
4911 Image_StripImageExtension(name, basename, sizeof(basename));
4913 if( last == NULL ) {
4915 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4916 item = r_skinframe.hash[hashindex];
4921 // linearly search through the hash bucket
4922 for( ; item ; item = item->next ) {
4923 if( !strcmp( item->basename, basename ) ) {
4930 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
4934 char basename[MAX_QPATH];
4936 Image_StripImageExtension(name, basename, sizeof(basename));
4938 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4939 for (item = r_skinframe.hash[hashindex];item;item = item->next)
4940 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
4944 rtexture_t *dyntexture;
4945 // check whether its a dynamic texture
4946 dyntexture = CL_GetDynTexture( basename );
4947 if (!add && !dyntexture)
4949 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
4950 memset(item, 0, sizeof(*item));
4951 strlcpy(item->basename, basename, sizeof(item->basename));
4952 item->base = dyntexture; // either NULL or dyntexture handle
4953 item->textureflags = textureflags;
4954 item->comparewidth = comparewidth;
4955 item->compareheight = compareheight;
4956 item->comparecrc = comparecrc;
4957 item->next = r_skinframe.hash[hashindex];
4958 r_skinframe.hash[hashindex] = item;
4960 else if( item->base == NULL )
4962 rtexture_t *dyntexture;
4963 // check whether its a dynamic texture
4964 // 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]
4965 dyntexture = CL_GetDynTexture( basename );
4966 item->base = dyntexture; // either NULL or dyntexture handle
4969 R_SkinFrame_MarkUsed(item);
4973 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
4975 unsigned long long avgcolor[5], wsum; \
4983 for(pix = 0; pix < cnt; ++pix) \
4986 for(comp = 0; comp < 3; ++comp) \
4988 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
4991 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4993 for(comp = 0; comp < 3; ++comp) \
4994 avgcolor[comp] += getpixel * w; \
4997 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4998 avgcolor[4] += getpixel; \
5000 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5002 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5003 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5004 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5005 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5008 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5011 unsigned char *pixels;
5012 unsigned char *bumppixels;
5013 unsigned char *basepixels = NULL;
5014 int basepixels_width = 0;
5015 int basepixels_height = 0;
5016 skinframe_t *skinframe;
5017 rtexture_t *ddsbase = NULL;
5018 qboolean ddshasalpha = false;
5019 float ddsavgcolor[4];
5020 char basename[MAX_QPATH];
5022 if (cls.state == ca_dedicated)
5025 // return an existing skinframe if already loaded
5026 // if loading of the first image fails, don't make a new skinframe as it
5027 // would cause all future lookups of this to be missing
5028 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5029 if (skinframe && skinframe->base)
5032 Image_StripImageExtension(name, basename, sizeof(basename));
5034 // check for DDS texture file first
5035 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5037 basepixels = loadimagepixelsbgra(name, complain, true);
5038 if (basepixels == NULL)
5042 if (developer_loading.integer)
5043 Con_Printf("loading skin \"%s\"\n", name);
5045 // we've got some pixels to store, so really allocate this new texture now
5047 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5048 skinframe->stain = NULL;
5049 skinframe->merged = NULL;
5050 skinframe->base = NULL;
5051 skinframe->pants = NULL;
5052 skinframe->shirt = NULL;
5053 skinframe->nmap = NULL;
5054 skinframe->gloss = NULL;
5055 skinframe->glow = NULL;
5056 skinframe->fog = NULL;
5057 skinframe->hasalpha = false;
5061 skinframe->base = ddsbase;
5062 skinframe->hasalpha = ddshasalpha;
5063 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5064 if (r_loadfog && skinframe->hasalpha)
5065 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5066 //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]);
5070 basepixels_width = image_width;
5071 basepixels_height = image_height;
5072 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);
5073 if (textureflags & TEXF_ALPHA)
5075 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5077 if (basepixels[j] < 255)
5079 skinframe->hasalpha = true;
5083 if (r_loadfog && skinframe->hasalpha)
5085 // has transparent pixels
5086 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5087 for (j = 0;j < image_width * image_height * 4;j += 4)
5092 pixels[j+3] = basepixels[j+3];
5094 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);
5098 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5099 //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]);
5100 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5101 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5102 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5103 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5108 if (r_loadnormalmap)
5109 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5110 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5112 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5113 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5114 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5117 // _norm is the name used by tenebrae and has been adopted as standard
5118 if (r_loadnormalmap && skinframe->nmap == NULL)
5120 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5122 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);
5126 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5128 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5129 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5130 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);
5132 Mem_Free(bumppixels);
5134 else if (r_shadow_bumpscale_basetexture.value > 0)
5136 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5137 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5138 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);
5141 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5142 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5145 // _luma is supported only for tenebrae compatibility
5146 // _glow is the preferred name
5147 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5149 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);
5150 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5151 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5152 Mem_Free(pixels);pixels = NULL;
5155 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5157 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);
5158 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5159 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5164 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5166 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);
5167 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5168 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5173 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5175 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);
5176 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5177 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5183 Mem_Free(basepixels);
5188 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5189 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5192 unsigned char *temp1, *temp2;
5193 skinframe_t *skinframe;
5195 if (cls.state == ca_dedicated)
5198 // if already loaded just return it, otherwise make a new skinframe
5199 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5200 if (skinframe && skinframe->base)
5203 skinframe->stain = NULL;
5204 skinframe->merged = NULL;
5205 skinframe->base = NULL;
5206 skinframe->pants = NULL;
5207 skinframe->shirt = NULL;
5208 skinframe->nmap = NULL;
5209 skinframe->gloss = NULL;
5210 skinframe->glow = NULL;
5211 skinframe->fog = NULL;
5212 skinframe->hasalpha = false;
5214 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5218 if (developer_loading.integer)
5219 Con_Printf("loading 32bit skin \"%s\"\n", name);
5221 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5223 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5224 temp2 = temp1 + width * height * 4;
5225 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5226 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5229 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5230 if (textureflags & TEXF_ALPHA)
5232 for (i = 3;i < width * height * 4;i += 4)
5234 if (skindata[i] < 255)
5236 skinframe->hasalpha = true;
5240 if (r_loadfog && skinframe->hasalpha)
5242 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5243 memcpy(fogpixels, skindata, width * height * 4);
5244 for (i = 0;i < width * height * 4;i += 4)
5245 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5246 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5247 Mem_Free(fogpixels);
5251 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5252 //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]);
5257 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5261 skinframe_t *skinframe;
5263 if (cls.state == ca_dedicated)
5266 // if already loaded just return it, otherwise make a new skinframe
5267 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5268 if (skinframe && skinframe->base)
5271 skinframe->stain = NULL;
5272 skinframe->merged = NULL;
5273 skinframe->base = NULL;
5274 skinframe->pants = NULL;
5275 skinframe->shirt = NULL;
5276 skinframe->nmap = NULL;
5277 skinframe->gloss = NULL;
5278 skinframe->glow = NULL;
5279 skinframe->fog = NULL;
5280 skinframe->hasalpha = false;
5282 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5286 if (developer_loading.integer)
5287 Con_Printf("loading quake skin \"%s\"\n", name);
5289 // 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)
5290 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5291 memcpy(skinframe->qpixels, skindata, width*height);
5292 skinframe->qwidth = width;
5293 skinframe->qheight = height;
5296 for (i = 0;i < width * height;i++)
5297 featuresmask |= palette_featureflags[skindata[i]];
5299 skinframe->hasalpha = false;
5300 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5301 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5302 skinframe->qgeneratemerged = true;
5303 skinframe->qgeneratebase = skinframe->qhascolormapping;
5304 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5306 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5307 //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]);
5312 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5316 unsigned char *skindata;
5318 if (!skinframe->qpixels)
5321 if (!skinframe->qhascolormapping)
5322 colormapped = false;
5326 if (!skinframe->qgeneratebase)
5331 if (!skinframe->qgeneratemerged)
5335 width = skinframe->qwidth;
5336 height = skinframe->qheight;
5337 skindata = skinframe->qpixels;
5339 if (skinframe->qgeneratenmap)
5341 unsigned char *temp1, *temp2;
5342 skinframe->qgeneratenmap = false;
5343 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5344 temp2 = temp1 + width * height * 4;
5345 // use either a custom palette or the quake palette
5346 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5347 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5348 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5352 if (skinframe->qgenerateglow)
5354 skinframe->qgenerateglow = false;
5355 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5360 skinframe->qgeneratebase = false;
5361 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);
5362 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5363 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5367 skinframe->qgeneratemerged = false;
5368 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5371 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5373 Mem_Free(skinframe->qpixels);
5374 skinframe->qpixels = NULL;
5378 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)
5381 skinframe_t *skinframe;
5383 if (cls.state == ca_dedicated)
5386 // if already loaded just return it, otherwise make a new skinframe
5387 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5388 if (skinframe && skinframe->base)
5391 skinframe->stain = NULL;
5392 skinframe->merged = NULL;
5393 skinframe->base = NULL;
5394 skinframe->pants = NULL;
5395 skinframe->shirt = NULL;
5396 skinframe->nmap = NULL;
5397 skinframe->gloss = NULL;
5398 skinframe->glow = NULL;
5399 skinframe->fog = NULL;
5400 skinframe->hasalpha = false;
5402 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5406 if (developer_loading.integer)
5407 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5409 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5410 if (textureflags & TEXF_ALPHA)
5412 for (i = 0;i < width * height;i++)
5414 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5416 skinframe->hasalpha = true;
5420 if (r_loadfog && skinframe->hasalpha)
5421 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5424 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5425 //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]);
5430 skinframe_t *R_SkinFrame_LoadMissing(void)
5432 skinframe_t *skinframe;
5434 if (cls.state == ca_dedicated)
5437 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5438 skinframe->stain = NULL;
5439 skinframe->merged = NULL;
5440 skinframe->base = NULL;
5441 skinframe->pants = NULL;
5442 skinframe->shirt = NULL;
5443 skinframe->nmap = NULL;
5444 skinframe->gloss = NULL;
5445 skinframe->glow = NULL;
5446 skinframe->fog = NULL;
5447 skinframe->hasalpha = false;
5449 skinframe->avgcolor[0] = rand() / RAND_MAX;
5450 skinframe->avgcolor[1] = rand() / RAND_MAX;
5451 skinframe->avgcolor[2] = rand() / RAND_MAX;
5452 skinframe->avgcolor[3] = 1;
5457 void R_Main_FreeViewCache(void)
5459 if (r_refdef.viewcache.entityvisible)
5460 Mem_Free(r_refdef.viewcache.entityvisible);
5461 if (r_refdef.viewcache.world_pvsbits)
5462 Mem_Free(r_refdef.viewcache.world_pvsbits);
5463 if (r_refdef.viewcache.world_leafvisible)
5464 Mem_Free(r_refdef.viewcache.world_leafvisible);
5465 if (r_refdef.viewcache.world_surfacevisible)
5466 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5467 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5470 void R_Main_ResizeViewCache(void)
5472 int numentities = r_refdef.scene.numentities;
5473 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5474 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5475 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5476 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5477 if (r_refdef.viewcache.maxentities < numentities)
5479 r_refdef.viewcache.maxentities = numentities;
5480 if (r_refdef.viewcache.entityvisible)
5481 Mem_Free(r_refdef.viewcache.entityvisible);
5482 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5484 if (r_refdef.viewcache.world_numclusters != numclusters)
5486 r_refdef.viewcache.world_numclusters = numclusters;
5487 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5488 if (r_refdef.viewcache.world_pvsbits)
5489 Mem_Free(r_refdef.viewcache.world_pvsbits);
5490 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5492 if (r_refdef.viewcache.world_numleafs != numleafs)
5494 r_refdef.viewcache.world_numleafs = numleafs;
5495 if (r_refdef.viewcache.world_leafvisible)
5496 Mem_Free(r_refdef.viewcache.world_leafvisible);
5497 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5499 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5501 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5502 if (r_refdef.viewcache.world_surfacevisible)
5503 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5504 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5508 extern rtexture_t *loadingscreentexture;
5509 void gl_main_start(void)
5511 loadingscreentexture = NULL;
5512 r_texture_blanknormalmap = NULL;
5513 r_texture_white = NULL;
5514 r_texture_grey128 = NULL;
5515 r_texture_black = NULL;
5516 r_texture_whitecube = NULL;
5517 r_texture_normalizationcube = NULL;
5518 r_texture_fogattenuation = NULL;
5519 r_texture_gammaramps = NULL;
5521 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5522 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5524 switch(vid.renderpath)
5526 case RENDERPATH_GL20:
5527 case RENDERPATH_CGGL:
5528 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5529 Cvar_SetValueQuick(&gl_combine, 1);
5530 Cvar_SetValueQuick(&r_glsl, 1);
5531 r_loadnormalmap = true;
5535 case RENDERPATH_GL13:
5536 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5537 Cvar_SetValueQuick(&gl_combine, 1);
5538 Cvar_SetValueQuick(&r_glsl, 0);
5539 r_loadnormalmap = false;
5540 r_loadgloss = false;
5543 case RENDERPATH_GL11:
5544 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5545 Cvar_SetValueQuick(&gl_combine, 0);
5546 Cvar_SetValueQuick(&r_glsl, 0);
5547 r_loadnormalmap = false;
5548 r_loadgloss = false;
5554 R_FrameData_Reset();
5558 memset(r_queries, 0, sizeof(r_queries));
5560 r_qwskincache = NULL;
5561 r_qwskincache_size = 0;
5563 // set up r_skinframe loading system for textures
5564 memset(&r_skinframe, 0, sizeof(r_skinframe));
5565 r_skinframe.loadsequence = 1;
5566 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5568 r_main_texturepool = R_AllocTexturePool();
5569 R_BuildBlankTextures();
5571 if (vid.support.arb_texture_cube_map)
5574 R_BuildNormalizationCube();
5576 r_texture_fogattenuation = NULL;
5577 r_texture_gammaramps = NULL;
5578 //r_texture_fogintensity = NULL;
5579 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5580 memset(&r_waterstate, 0, sizeof(r_waterstate));
5581 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5582 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5584 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5585 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5587 memset(&r_svbsp, 0, sizeof (r_svbsp));
5589 r_refdef.fogmasktable_density = 0;
5592 void gl_main_shutdown(void)
5595 R_FrameData_Reset();
5597 R_Main_FreeViewCache();
5600 qglDeleteQueriesARB(r_maxqueries, r_queries);
5604 memset(r_queries, 0, sizeof(r_queries));
5606 r_qwskincache = NULL;
5607 r_qwskincache_size = 0;
5609 // clear out the r_skinframe state
5610 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5611 memset(&r_skinframe, 0, sizeof(r_skinframe));
5614 Mem_Free(r_svbsp.nodes);
5615 memset(&r_svbsp, 0, sizeof (r_svbsp));
5616 R_FreeTexturePool(&r_main_texturepool);
5617 loadingscreentexture = NULL;
5618 r_texture_blanknormalmap = NULL;
5619 r_texture_white = NULL;
5620 r_texture_grey128 = NULL;
5621 r_texture_black = NULL;
5622 r_texture_whitecube = NULL;
5623 r_texture_normalizationcube = NULL;
5624 r_texture_fogattenuation = NULL;
5625 r_texture_gammaramps = NULL;
5626 //r_texture_fogintensity = NULL;
5627 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5628 memset(&r_waterstate, 0, sizeof(r_waterstate));
5632 extern void CL_ParseEntityLump(char *entitystring);
5633 void gl_main_newmap(void)
5635 // FIXME: move this code to client
5637 char *entities, entname[MAX_QPATH];
5639 Mem_Free(r_qwskincache);
5640 r_qwskincache = NULL;
5641 r_qwskincache_size = 0;
5644 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5645 l = (int)strlen(entname) - 4;
5646 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5648 memcpy(entname + l, ".ent", 5);
5649 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5651 CL_ParseEntityLump(entities);
5656 if (cl.worldmodel->brush.entities)
5657 CL_ParseEntityLump(cl.worldmodel->brush.entities);
5659 R_Main_FreeViewCache();
5661 R_FrameData_Reset();
5664 void GL_Main_Init(void)
5666 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5668 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5669 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5670 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5671 if (gamemode == GAME_NEHAHRA)
5673 Cvar_RegisterVariable (&gl_fogenable);
5674 Cvar_RegisterVariable (&gl_fogdensity);
5675 Cvar_RegisterVariable (&gl_fogred);
5676 Cvar_RegisterVariable (&gl_foggreen);
5677 Cvar_RegisterVariable (&gl_fogblue);
5678 Cvar_RegisterVariable (&gl_fogstart);
5679 Cvar_RegisterVariable (&gl_fogend);
5680 Cvar_RegisterVariable (&gl_skyclip);
5682 Cvar_RegisterVariable(&r_motionblur);
5683 Cvar_RegisterVariable(&r_motionblur_maxblur);
5684 Cvar_RegisterVariable(&r_motionblur_bmin);
5685 Cvar_RegisterVariable(&r_motionblur_vmin);
5686 Cvar_RegisterVariable(&r_motionblur_vmax);
5687 Cvar_RegisterVariable(&r_motionblur_vcoeff);
5688 Cvar_RegisterVariable(&r_motionblur_randomize);
5689 Cvar_RegisterVariable(&r_damageblur);
5690 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5691 Cvar_RegisterVariable(&r_equalize_entities_minambient);
5692 Cvar_RegisterVariable(&r_equalize_entities_by);
5693 Cvar_RegisterVariable(&r_equalize_entities_to);
5694 Cvar_RegisterVariable(&r_depthfirst);
5695 Cvar_RegisterVariable(&r_useinfinitefarclip);
5696 Cvar_RegisterVariable(&r_farclip_base);
5697 Cvar_RegisterVariable(&r_farclip_world);
5698 Cvar_RegisterVariable(&r_nearclip);
5699 Cvar_RegisterVariable(&r_showbboxes);
5700 Cvar_RegisterVariable(&r_showsurfaces);
5701 Cvar_RegisterVariable(&r_showtris);
5702 Cvar_RegisterVariable(&r_shownormals);
5703 Cvar_RegisterVariable(&r_showlighting);
5704 Cvar_RegisterVariable(&r_showshadowvolumes);
5705 Cvar_RegisterVariable(&r_showcollisionbrushes);
5706 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5707 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5708 Cvar_RegisterVariable(&r_showdisabledepthtest);
5709 Cvar_RegisterVariable(&r_drawportals);
5710 Cvar_RegisterVariable(&r_drawentities);
5711 Cvar_RegisterVariable(&r_cullentities_trace);
5712 Cvar_RegisterVariable(&r_cullentities_trace_samples);
5713 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5714 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5715 Cvar_RegisterVariable(&r_cullentities_trace_delay);
5716 Cvar_RegisterVariable(&r_drawviewmodel);
5717 Cvar_RegisterVariable(&r_speeds);
5718 Cvar_RegisterVariable(&r_fullbrights);
5719 Cvar_RegisterVariable(&r_wateralpha);
5720 Cvar_RegisterVariable(&r_dynamic);
5721 Cvar_RegisterVariable(&r_fullbright);
5722 Cvar_RegisterVariable(&r_shadows);
5723 Cvar_RegisterVariable(&r_shadows_darken);
5724 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5725 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5726 Cvar_RegisterVariable(&r_shadows_throwdistance);
5727 Cvar_RegisterVariable(&r_shadows_throwdirection);
5728 Cvar_RegisterVariable(&r_q1bsp_skymasking);
5729 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5730 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5731 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5732 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5733 Cvar_RegisterVariable(&r_fog_exp2);
5734 Cvar_RegisterVariable(&r_drawfog);
5735 Cvar_RegisterVariable(&r_transparentdepthmasking);
5736 Cvar_RegisterVariable(&r_texture_dds_load);
5737 Cvar_RegisterVariable(&r_texture_dds_save);
5738 Cvar_RegisterVariable(&r_textureunits);
5739 Cvar_RegisterVariable(&gl_combine);
5740 Cvar_RegisterVariable(&r_glsl);
5741 Cvar_RegisterVariable(&r_glsl_deluxemapping);
5742 Cvar_RegisterVariable(&r_glsl_offsetmapping);
5743 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5744 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5745 Cvar_RegisterVariable(&r_glsl_postprocess);
5746 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5747 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5748 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5749 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5750 Cvar_RegisterVariable(&r_water);
5751 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5752 Cvar_RegisterVariable(&r_water_clippingplanebias);
5753 Cvar_RegisterVariable(&r_water_refractdistort);
5754 Cvar_RegisterVariable(&r_water_reflectdistort);
5755 Cvar_RegisterVariable(&r_lerpsprites);
5756 Cvar_RegisterVariable(&r_lerpmodels);
5757 Cvar_RegisterVariable(&r_lerplightstyles);
5758 Cvar_RegisterVariable(&r_waterscroll);
5759 Cvar_RegisterVariable(&r_bloom);
5760 Cvar_RegisterVariable(&r_bloom_colorscale);
5761 Cvar_RegisterVariable(&r_bloom_brighten);
5762 Cvar_RegisterVariable(&r_bloom_blur);
5763 Cvar_RegisterVariable(&r_bloom_resolution);
5764 Cvar_RegisterVariable(&r_bloom_colorexponent);
5765 Cvar_RegisterVariable(&r_bloom_colorsubtract);
5766 Cvar_RegisterVariable(&r_hdr);
5767 Cvar_RegisterVariable(&r_hdr_scenebrightness);
5768 Cvar_RegisterVariable(&r_hdr_glowintensity);
5769 Cvar_RegisterVariable(&r_hdr_range);
5770 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5771 Cvar_RegisterVariable(&developer_texturelogging);
5772 Cvar_RegisterVariable(&gl_lightmaps);
5773 Cvar_RegisterVariable(&r_test);
5774 Cvar_RegisterVariable(&r_batchmode);
5775 Cvar_RegisterVariable(&r_glsl_saturation);
5776 Cvar_RegisterVariable(&r_framedatasize);
5777 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5778 Cvar_SetValue("r_fullbrights", 0);
5779 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5781 Cvar_RegisterVariable(&r_track_sprites);
5782 Cvar_RegisterVariable(&r_track_sprites_flags);
5783 Cvar_RegisterVariable(&r_track_sprites_scalew);
5784 Cvar_RegisterVariable(&r_track_sprites_scaleh);
5787 extern void R_Textures_Init(void);
5788 extern void GL_Draw_Init(void);
5789 extern void GL_Main_Init(void);
5790 extern void R_Shadow_Init(void);
5791 extern void R_Sky_Init(void);
5792 extern void GL_Surf_Init(void);
5793 extern void R_Particles_Init(void);
5794 extern void R_Explosion_Init(void);
5795 extern void gl_backend_init(void);
5796 extern void Sbar_Init(void);
5797 extern void R_LightningBeams_Init(void);
5798 extern void Mod_RenderInit(void);
5799 extern void Font_Init(void);
5801 void Render_Init(void)
5814 R_LightningBeams_Init();
5823 extern char *ENGINE_EXTENSIONS;
5826 gl_renderer = (const char *)qglGetString(GL_RENDERER);
5827 gl_vendor = (const char *)qglGetString(GL_VENDOR);
5828 gl_version = (const char *)qglGetString(GL_VERSION);
5829 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5833 if (!gl_platformextensions)
5834 gl_platformextensions = "";
5836 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5837 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5838 Con_Printf("GL_VERSION: %s\n", gl_version);
5839 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
5840 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
5842 VID_CheckExtensions();
5844 // LordHavoc: report supported extensions
5845 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
5847 // clear to black (loading plaque will be seen over this)
5849 qglClearColor(0,0,0,1);CHECKGLERROR
5850 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
5853 int R_CullBox(const vec3_t mins, const vec3_t maxs)
5857 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5859 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
5862 p = r_refdef.view.frustum + i;
5867 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5871 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5875 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5879 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5883 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5887 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5891 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5895 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5903 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
5907 for (i = 0;i < numplanes;i++)
5914 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5918 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5922 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5926 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5930 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5934 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5938 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5942 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5950 //==================================================================================
5952 // LordHavoc: this stores temporary data used within the same frame
5954 qboolean r_framedata_failed;
5955 static size_t r_framedata_size;
5956 static size_t r_framedata_current;
5957 static void *r_framedata_base;
5959 void R_FrameData_Reset(void)
5961 if (r_framedata_base)
5962 Mem_Free(r_framedata_base);
5963 r_framedata_base = NULL;
5964 r_framedata_size = 0;
5965 r_framedata_current = 0;
5966 r_framedata_failed = false;
5969 void R_FrameData_NewFrame(void)
5972 if (r_framedata_failed)
5973 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
5974 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
5975 wantedsize = bound(65536, wantedsize, 128*1024*1024);
5976 if (r_framedata_size != wantedsize)
5978 r_framedata_size = wantedsize;
5979 if (r_framedata_base)
5980 Mem_Free(r_framedata_base);
5981 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
5983 r_framedata_current = 0;
5984 r_framedata_failed = false;
5987 void *R_FrameData_Alloc(size_t size)
5991 // align to 16 byte boundary
5992 size = (size + 15) & ~15;
5993 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
5994 r_framedata_current += size;
5997 if (r_framedata_current > r_framedata_size)
5998 r_framedata_failed = true;
6000 // return NULL on everything after a failure
6001 if (r_framedata_failed)
6007 void *R_FrameData_Store(size_t size, void *data)
6009 void *d = R_FrameData_Alloc(size);
6011 memcpy(d, data, size);
6015 //==================================================================================
6017 // LordHavoc: animcache originally written by Echon, rewritten since then
6020 * Animation cache prevents re-generating mesh data for an animated model
6021 * multiple times in one frame for lighting, shadowing, reflections, etc.
6024 void R_AnimCache_Free(void)
6028 void R_AnimCache_ClearCache(void)
6031 entity_render_t *ent;
6033 for (i = 0;i < r_refdef.scene.numentities;i++)
6035 ent = r_refdef.scene.entities[i];
6036 ent->animcache_vertex3f = NULL;
6037 ent->animcache_normal3f = NULL;
6038 ent->animcache_svector3f = NULL;
6039 ent->animcache_tvector3f = NULL;
6043 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6045 dp_model_t *model = ent->model;
6047 // see if it's already cached this frame
6048 if (ent->animcache_vertex3f)
6050 // add normals/tangents if needed
6051 if (wantnormals || wanttangents)
6053 if (ent->animcache_normal3f)
6054 wantnormals = false;
6055 if (ent->animcache_svector3f)
6056 wanttangents = false;
6057 if (wantnormals || wanttangents)
6059 numvertices = model->surfmesh.num_vertices;
6061 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6064 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6065 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6067 if (!r_framedata_failed)
6068 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6074 // see if this ent is worth caching
6075 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6077 // get some memory for this entity and generate mesh data
6078 numvertices = model->surfmesh.num_vertices;
6079 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6081 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6084 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6085 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6087 if (!r_framedata_failed)
6088 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6090 return !r_framedata_failed;
6093 void R_AnimCache_CacheVisibleEntities(void)
6096 qboolean wantnormals = !r_showsurfaces.integer;
6097 qboolean wanttangents = !r_showsurfaces.integer;
6099 switch(vid.renderpath)
6101 case RENDERPATH_GL20:
6102 case RENDERPATH_CGGL:
6104 case RENDERPATH_GL13:
6105 case RENDERPATH_GL11:
6106 wanttangents = false;
6110 // TODO: thread this
6111 // NOTE: R_PrepareRTLights() also caches entities
6113 for (i = 0;i < r_refdef.scene.numentities;i++)
6114 if (r_refdef.viewcache.entityvisible[i])
6115 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6117 if (r_shadows.integer)
6118 for (i = 0;i < r_refdef.scene.numentities;i++)
6119 if (!r_refdef.viewcache.entityvisible[i])
6120 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6123 //==================================================================================
6125 static void R_View_UpdateEntityLighting (void)
6128 entity_render_t *ent;
6129 vec3_t tempdiffusenormal, avg;
6130 vec_t f, fa, fd, fdd;
6132 for (i = 0;i < r_refdef.scene.numentities;i++)
6134 ent = r_refdef.scene.entities[i];
6136 // skip unseen models
6137 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6141 if (ent->model && ent->model->brush.num_leafs)
6143 // TODO: use modellight for r_ambient settings on world?
6144 VectorSet(ent->modellight_ambient, 0, 0, 0);
6145 VectorSet(ent->modellight_diffuse, 0, 0, 0);
6146 VectorSet(ent->modellight_lightdir, 0, 0, 1);
6150 // fetch the lighting from the worldmodel data
6151 VectorClear(ent->modellight_ambient);
6152 VectorClear(ent->modellight_diffuse);
6153 VectorClear(tempdiffusenormal);
6154 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6157 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6158 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6159 if(ent->flags & RENDER_EQUALIZE)
6161 // first fix up ambient lighting...
6162 if(r_equalize_entities_minambient.value > 0)
6164 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6167 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6168 if(fa < r_equalize_entities_minambient.value * fd)
6171 // fa'/fd' = minambient
6172 // fa'+0.25*fd' = fa+0.25*fd
6174 // fa' = fd' * minambient
6175 // fd'*(0.25+minambient) = fa+0.25*fd
6177 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6178 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6180 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6181 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
6182 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6183 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6188 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6190 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6191 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6194 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6195 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6196 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6202 VectorSet(ent->modellight_ambient, 1, 1, 1);
6204 // move the light direction into modelspace coordinates for lighting code
6205 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6206 if(VectorLength2(ent->modellight_lightdir) == 0)
6207 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6208 VectorNormalize(ent->modellight_lightdir);
6212 #define MAX_LINEOFSIGHTTRACES 64
6214 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6217 vec3_t boxmins, boxmaxs;
6220 dp_model_t *model = r_refdef.scene.worldmodel;
6222 if (!model || !model->brush.TraceLineOfSight)
6225 // expand the box a little
6226 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6227 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6228 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6229 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6230 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6231 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6234 VectorCopy(eye, start);
6235 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6236 if (model->brush.TraceLineOfSight(model, start, end))
6239 // try various random positions
6240 for (i = 0;i < numsamples;i++)
6242 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6243 if (model->brush.TraceLineOfSight(model, start, end))
6251 static void R_View_UpdateEntityVisible (void)
6256 entity_render_t *ent;
6258 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6259 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6261 // worldmodel can check visibility
6262 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6263 for (i = 0;i < r_refdef.scene.numentities;i++)
6265 ent = r_refdef.scene.entities[i];
6266 if (!(ent->flags & renderimask))
6267 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)))
6268 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))
6269 r_refdef.viewcache.entityvisible[i] = true;
6271 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6273 for (i = 0;i < r_refdef.scene.numentities;i++)
6275 ent = r_refdef.scene.entities[i];
6276 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6278 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6280 continue; // temp entities do pvs only
6281 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6282 ent->last_trace_visibility = realtime;
6283 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6284 r_refdef.viewcache.entityvisible[i] = 0;
6291 // no worldmodel or it can't check visibility
6292 for (i = 0;i < r_refdef.scene.numentities;i++)
6294 ent = r_refdef.scene.entities[i];
6295 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));
6300 /// only used if skyrendermasked, and normally returns false
6301 int R_DrawBrushModelsSky (void)
6304 entity_render_t *ent;
6307 for (i = 0;i < r_refdef.scene.numentities;i++)
6309 if (!r_refdef.viewcache.entityvisible[i])
6311 ent = r_refdef.scene.entities[i];
6312 if (!ent->model || !ent->model->DrawSky)
6314 ent->model->DrawSky(ent);
6320 static void R_DrawNoModel(entity_render_t *ent);
6321 static void R_DrawModels(void)
6324 entity_render_t *ent;
6326 for (i = 0;i < r_refdef.scene.numentities;i++)
6328 if (!r_refdef.viewcache.entityvisible[i])
6330 ent = r_refdef.scene.entities[i];
6331 r_refdef.stats.entities++;
6332 if (ent->model && ent->model->Draw != NULL)
6333 ent->model->Draw(ent);
6339 static void R_DrawModelsDepth(void)
6342 entity_render_t *ent;
6344 for (i = 0;i < r_refdef.scene.numentities;i++)
6346 if (!r_refdef.viewcache.entityvisible[i])
6348 ent = r_refdef.scene.entities[i];
6349 if (ent->model && ent->model->DrawDepth != NULL)
6350 ent->model->DrawDepth(ent);
6354 static void R_DrawModelsDebug(void)
6357 entity_render_t *ent;
6359 for (i = 0;i < r_refdef.scene.numentities;i++)
6361 if (!r_refdef.viewcache.entityvisible[i])
6363 ent = r_refdef.scene.entities[i];
6364 if (ent->model && ent->model->DrawDebug != NULL)
6365 ent->model->DrawDebug(ent);
6369 static void R_DrawModelsAddWaterPlanes(void)
6372 entity_render_t *ent;
6374 for (i = 0;i < r_refdef.scene.numentities;i++)
6376 if (!r_refdef.viewcache.entityvisible[i])
6378 ent = r_refdef.scene.entities[i];
6379 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6380 ent->model->DrawAddWaterPlanes(ent);
6384 static void R_View_SetFrustum(void)
6387 double slopex, slopey;
6388 vec3_t forward, left, up, origin;
6390 // we can't trust r_refdef.view.forward and friends in reflected scenes
6391 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6394 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6395 r_refdef.view.frustum[0].normal[1] = 0 - 0;
6396 r_refdef.view.frustum[0].normal[2] = -1 - 0;
6397 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6398 r_refdef.view.frustum[1].normal[1] = 0 + 0;
6399 r_refdef.view.frustum[1].normal[2] = -1 + 0;
6400 r_refdef.view.frustum[2].normal[0] = 0 - 0;
6401 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6402 r_refdef.view.frustum[2].normal[2] = -1 - 0;
6403 r_refdef.view.frustum[3].normal[0] = 0 + 0;
6404 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6405 r_refdef.view.frustum[3].normal[2] = -1 + 0;
6409 zNear = r_refdef.nearclip;
6410 nudge = 1.0 - 1.0 / (1<<23);
6411 r_refdef.view.frustum[4].normal[0] = 0 - 0;
6412 r_refdef.view.frustum[4].normal[1] = 0 - 0;
6413 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6414 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6415 r_refdef.view.frustum[5].normal[0] = 0 + 0;
6416 r_refdef.view.frustum[5].normal[1] = 0 + 0;
6417 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6418 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6424 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6425 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6426 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6427 r_refdef.view.frustum[0].dist = m[15] - m[12];
6429 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6430 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6431 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6432 r_refdef.view.frustum[1].dist = m[15] + m[12];
6434 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6435 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6436 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6437 r_refdef.view.frustum[2].dist = m[15] - m[13];
6439 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6440 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6441 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6442 r_refdef.view.frustum[3].dist = m[15] + m[13];
6444 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6445 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6446 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6447 r_refdef.view.frustum[4].dist = m[15] - m[14];
6449 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6450 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6451 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6452 r_refdef.view.frustum[5].dist = m[15] + m[14];
6455 if (r_refdef.view.useperspective)
6457 slopex = 1.0 / r_refdef.view.frustum_x;
6458 slopey = 1.0 / r_refdef.view.frustum_y;
6459 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6460 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
6461 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
6462 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
6463 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6465 // Leaving those out was a mistake, those were in the old code, and they
6466 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6467 // I couldn't reproduce it after adding those normalizations. --blub
6468 VectorNormalize(r_refdef.view.frustum[0].normal);
6469 VectorNormalize(r_refdef.view.frustum[1].normal);
6470 VectorNormalize(r_refdef.view.frustum[2].normal);
6471 VectorNormalize(r_refdef.view.frustum[3].normal);
6473 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6474 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]);
6475 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]);
6476 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]);
6477 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]);
6479 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6480 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6481 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6482 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6483 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6487 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6488 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6489 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6490 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6491 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6492 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6493 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6494 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6495 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6496 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6498 r_refdef.view.numfrustumplanes = 5;
6500 if (r_refdef.view.useclipplane)
6502 r_refdef.view.numfrustumplanes = 6;
6503 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6506 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6507 PlaneClassify(r_refdef.view.frustum + i);
6509 // LordHavoc: note to all quake engine coders, Quake had a special case
6510 // for 90 degrees which assumed a square view (wrong), so I removed it,
6511 // Quake2 has it disabled as well.
6513 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6514 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6515 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6516 //PlaneClassify(&frustum[0]);
6518 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6519 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6520 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6521 //PlaneClassify(&frustum[1]);
6523 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6524 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6525 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6526 //PlaneClassify(&frustum[2]);
6528 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6529 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6530 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6531 //PlaneClassify(&frustum[3]);
6534 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6535 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6536 //PlaneClassify(&frustum[4]);
6539 void R_View_Update(void)
6541 R_Main_ResizeViewCache();
6542 R_View_SetFrustum();
6543 R_View_WorldVisibility(r_refdef.view.useclipplane);
6544 R_View_UpdateEntityVisible();
6545 R_View_UpdateEntityLighting();
6548 void R_SetupView(qboolean allowwaterclippingplane)
6550 const float *customclipplane = NULL;
6552 if (r_refdef.view.useclipplane && allowwaterclippingplane)
6554 // LordHavoc: couldn't figure out how to make this approach the
6555 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6556 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6557 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6558 dist = r_refdef.view.clipplane.dist;
6559 plane[0] = r_refdef.view.clipplane.normal[0];
6560 plane[1] = r_refdef.view.clipplane.normal[1];
6561 plane[2] = r_refdef.view.clipplane.normal[2];
6563 customclipplane = plane;
6566 if (!r_refdef.view.useperspective)
6567 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);
6568 else if (vid.stencil && r_useinfinitefarclip.integer)
6569 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);
6571 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);
6572 R_SetViewport(&r_refdef.view.viewport);
6575 void R_EntityMatrix(const matrix4x4_t *matrix)
6577 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6579 gl_modelmatrixchanged = false;
6580 gl_modelmatrix = *matrix;
6581 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6582 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6583 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6584 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6586 switch(vid.renderpath)
6588 case RENDERPATH_GL20:
6589 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6590 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6592 case RENDERPATH_CGGL:
6595 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6596 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6599 case RENDERPATH_GL13:
6600 case RENDERPATH_GL11:
6601 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6607 void R_ResetViewRendering2D(void)
6609 r_viewport_t viewport;
6612 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6613 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);
6614 R_SetViewport(&viewport);
6615 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6616 GL_Color(1, 1, 1, 1);
6617 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6618 GL_BlendFunc(GL_ONE, GL_ZERO);
6619 GL_AlphaTest(false);
6620 GL_ScissorTest(false);
6621 GL_DepthMask(false);
6622 GL_DepthRange(0, 1);
6623 GL_DepthTest(false);
6624 R_EntityMatrix(&identitymatrix);
6625 R_Mesh_ResetTextureState();
6626 GL_PolygonOffset(0, 0);
6627 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6628 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6629 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6630 qglStencilMask(~0);CHECKGLERROR
6631 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6632 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6633 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6636 void R_ResetViewRendering3D(void)
6641 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6642 GL_Color(1, 1, 1, 1);
6643 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6644 GL_BlendFunc(GL_ONE, GL_ZERO);
6645 GL_AlphaTest(false);
6646 GL_ScissorTest(true);
6648 GL_DepthRange(0, 1);
6650 R_EntityMatrix(&identitymatrix);
6651 R_Mesh_ResetTextureState();
6652 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6653 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6654 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6655 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6656 qglStencilMask(~0);CHECKGLERROR
6657 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6658 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6659 GL_CullFace(r_refdef.view.cullface_back);
6662 void R_RenderScene(void);
6663 void R_RenderWaterPlanes(void);
6665 static void R_Water_StartFrame(void)
6668 int waterwidth, waterheight, texturewidth, textureheight;
6669 r_waterstate_waterplane_t *p;
6671 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6674 switch(vid.renderpath)
6676 case RENDERPATH_GL20:
6677 case RENDERPATH_CGGL:
6679 case RENDERPATH_GL13:
6680 case RENDERPATH_GL11:
6684 // set waterwidth and waterheight to the water resolution that will be
6685 // used (often less than the screen resolution for faster rendering)
6686 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6687 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6689 // calculate desired texture sizes
6690 // can't use water if the card does not support the texture size
6691 if (!r_water.integer || r_showsurfaces.integer)
6692 texturewidth = textureheight = waterwidth = waterheight = 0;
6693 else if (vid.support.arb_texture_non_power_of_two)
6695 texturewidth = waterwidth;
6696 textureheight = waterheight;
6700 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
6701 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
6704 // allocate textures as needed
6705 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6707 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6708 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6710 if (p->texture_refraction)
6711 R_FreeTexture(p->texture_refraction);
6712 p->texture_refraction = NULL;
6713 if (p->texture_reflection)
6714 R_FreeTexture(p->texture_reflection);
6715 p->texture_reflection = NULL;
6717 memset(&r_waterstate, 0, sizeof(r_waterstate));
6718 r_waterstate.texturewidth = texturewidth;
6719 r_waterstate.textureheight = textureheight;
6722 if (r_waterstate.texturewidth)
6724 r_waterstate.enabled = true;
6726 // when doing a reduced render (HDR) we want to use a smaller area
6727 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6728 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6730 // set up variables that will be used in shader setup
6731 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6732 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6733 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6734 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6737 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6738 r_waterstate.numwaterplanes = 0;
6741 void R_Water_AddWaterPlane(msurface_t *surface)
6743 int triangleindex, planeindex;
6749 r_waterstate_waterplane_t *p;
6750 texture_t *t = R_GetCurrentTexture(surface->texture);
6751 // just use the first triangle with a valid normal for any decisions
6752 VectorClear(normal);
6753 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6755 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6756 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6757 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6758 TriangleNormal(vert[0], vert[1], vert[2], normal);
6759 if (VectorLength2(normal) >= 0.001)
6763 VectorCopy(normal, plane.normal);
6764 VectorNormalize(plane.normal);
6765 plane.dist = DotProduct(vert[0], plane.normal);
6766 PlaneClassify(&plane);
6767 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6769 // skip backfaces (except if nocullface is set)
6770 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6772 VectorNegate(plane.normal, plane.normal);
6774 PlaneClassify(&plane);
6778 // find a matching plane if there is one
6779 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6780 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6782 if (planeindex >= r_waterstate.maxwaterplanes)
6783 return; // nothing we can do, out of planes
6785 // if this triangle does not fit any known plane rendered this frame, add one
6786 if (planeindex >= r_waterstate.numwaterplanes)
6788 // store the new plane
6789 r_waterstate.numwaterplanes++;
6791 // clear materialflags and pvs
6792 p->materialflags = 0;
6793 p->pvsvalid = false;
6795 // merge this surface's materialflags into the waterplane
6796 p->materialflags |= t->currentmaterialflags;
6797 // merge this surface's PVS into the waterplane
6798 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6799 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6800 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6802 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6807 static void R_Water_ProcessPlanes(void)
6809 r_refdef_view_t originalview;
6810 r_refdef_view_t myview;
6812 r_waterstate_waterplane_t *p;
6814 originalview = r_refdef.view;
6816 // make sure enough textures are allocated
6817 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6819 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6821 if (!p->texture_refraction)
6822 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);
6823 if (!p->texture_refraction)
6827 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6829 if (!p->texture_reflection)
6830 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);
6831 if (!p->texture_reflection)
6837 r_refdef.view = originalview;
6838 r_refdef.view.showdebug = false;
6839 r_refdef.view.width = r_waterstate.waterwidth;
6840 r_refdef.view.height = r_waterstate.waterheight;
6841 r_refdef.view.useclipplane = true;
6842 myview = r_refdef.view;
6843 r_waterstate.renderingscene = true;
6844 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6846 // render the normal view scene and copy into texture
6847 // (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)
6848 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6850 r_refdef.view = myview;
6851 r_refdef.view.clipplane = p->plane;
6852 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6853 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6854 PlaneClassify(&r_refdef.view.clipplane);
6856 R_ResetViewRendering3D();
6857 R_ClearScreen(r_refdef.fogenabled);
6861 R_Mesh_CopyToTexture(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);
6864 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6866 r_refdef.view = myview;
6867 // render reflected scene and copy into texture
6868 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6869 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6870 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6871 r_refdef.view.clipplane = p->plane;
6872 // reverse the cullface settings for this render
6873 r_refdef.view.cullface_front = GL_FRONT;
6874 r_refdef.view.cullface_back = GL_BACK;
6875 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6877 r_refdef.view.usecustompvs = true;
6879 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6881 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6884 R_ResetViewRendering3D();
6885 R_ClearScreen(r_refdef.fogenabled);
6889 R_Mesh_CopyToTexture(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);
6892 r_waterstate.renderingscene = false;
6893 r_refdef.view = originalview;
6894 R_ResetViewRendering3D();
6895 R_ClearScreen(r_refdef.fogenabled);
6899 r_refdef.view = originalview;
6900 r_waterstate.renderingscene = false;
6901 Cvar_SetValueQuick(&r_water, 0);
6902 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6906 void R_Bloom_StartFrame(void)
6908 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6910 switch(vid.renderpath)
6912 case RENDERPATH_GL20:
6913 case RENDERPATH_CGGL:
6915 case RENDERPATH_GL13:
6916 case RENDERPATH_GL11:
6920 // set bloomwidth and bloomheight to the bloom resolution that will be
6921 // used (often less than the screen resolution for faster rendering)
6922 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6923 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6924 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6925 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6926 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6928 // calculate desired texture sizes
6929 if (vid.support.arb_texture_non_power_of_two)
6931 screentexturewidth = r_refdef.view.width;
6932 screentextureheight = r_refdef.view.height;
6933 bloomtexturewidth = r_bloomstate.bloomwidth;
6934 bloomtextureheight = r_bloomstate.bloomheight;
6938 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6939 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6940 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
6941 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
6944 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))
6946 Cvar_SetValueQuick(&r_hdr, 0);
6947 Cvar_SetValueQuick(&r_bloom, 0);
6948 Cvar_SetValueQuick(&r_motionblur, 0);
6949 Cvar_SetValueQuick(&r_damageblur, 0);
6952 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)))
6953 screentexturewidth = screentextureheight = 0;
6954 if (!r_hdr.integer && !r_bloom.integer)
6955 bloomtexturewidth = bloomtextureheight = 0;
6957 // allocate textures as needed
6958 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
6960 if (r_bloomstate.texture_screen)
6961 R_FreeTexture(r_bloomstate.texture_screen);
6962 r_bloomstate.texture_screen = NULL;
6963 r_bloomstate.screentexturewidth = screentexturewidth;
6964 r_bloomstate.screentextureheight = screentextureheight;
6965 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6966 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
6968 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
6970 if (r_bloomstate.texture_bloom)
6971 R_FreeTexture(r_bloomstate.texture_bloom);
6972 r_bloomstate.texture_bloom = NULL;
6973 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6974 r_bloomstate.bloomtextureheight = bloomtextureheight;
6975 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6976 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6979 // when doing a reduced render (HDR) we want to use a smaller area
6980 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6981 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6982 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6983 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6984 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6986 // set up a texcoord array for the full resolution screen image
6987 // (we have to keep this around to copy back during final render)
6988 r_bloomstate.screentexcoord2f[0] = 0;
6989 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
6990 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
6991 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
6992 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
6993 r_bloomstate.screentexcoord2f[5] = 0;
6994 r_bloomstate.screentexcoord2f[6] = 0;
6995 r_bloomstate.screentexcoord2f[7] = 0;
6997 // set up a texcoord array for the reduced resolution bloom image
6998 // (which will be additive blended over the screen image)
6999 r_bloomstate.bloomtexcoord2f[0] = 0;
7000 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7001 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7002 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7003 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7004 r_bloomstate.bloomtexcoord2f[5] = 0;
7005 r_bloomstate.bloomtexcoord2f[6] = 0;
7006 r_bloomstate.bloomtexcoord2f[7] = 0;
7008 if (r_hdr.integer || r_bloom.integer)
7010 r_bloomstate.enabled = true;
7011 r_bloomstate.hdr = r_hdr.integer != 0;
7014 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);
7017 void R_Bloom_CopyBloomTexture(float colorscale)
7019 r_refdef.stats.bloom++;
7021 // scale down screen texture to the bloom texture size
7023 R_SetViewport(&r_bloomstate.viewport);
7024 GL_BlendFunc(GL_ONE, GL_ZERO);
7025 GL_Color(colorscale, colorscale, colorscale, 1);
7026 // TODO: optimize with multitexture or GLSL
7027 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7028 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7029 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7030 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7032 // we now have a bloom image in the framebuffer
7033 // copy it into the bloom image texture for later processing
7034 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7035 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7038 void R_Bloom_CopyHDRTexture(void)
7040 R_Mesh_CopyToTexture(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);
7041 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7044 void R_Bloom_MakeTexture(void)
7047 float xoffset, yoffset, r, brighten;
7049 r_refdef.stats.bloom++;
7051 R_ResetViewRendering2D();
7052 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7053 R_Mesh_ColorPointer(NULL, 0, 0);
7055 // we have a bloom image in the framebuffer
7057 R_SetViewport(&r_bloomstate.viewport);
7059 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7062 r = bound(0, r_bloom_colorexponent.value / x, 1);
7063 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7064 GL_Color(r, r, r, 1);
7065 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7066 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7067 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7068 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7070 // copy the vertically blurred bloom view to a texture
7071 GL_ActiveTexture(0);
7073 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7074 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7077 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7078 brighten = r_bloom_brighten.value;
7080 brighten *= r_hdr_range.value;
7081 brighten = sqrt(brighten);
7083 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7084 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7085 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7087 for (dir = 0;dir < 2;dir++)
7089 // blend on at multiple vertical offsets to achieve a vertical blur
7090 // TODO: do offset blends using GLSL
7091 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7092 GL_BlendFunc(GL_ONE, GL_ZERO);
7093 for (x = -range;x <= range;x++)
7095 if (!dir){xoffset = 0;yoffset = x;}
7096 else {xoffset = x;yoffset = 0;}
7097 xoffset /= (float)r_bloomstate.bloomtexturewidth;
7098 yoffset /= (float)r_bloomstate.bloomtextureheight;
7099 // compute a texcoord array with the specified x and y offset
7100 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7101 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7102 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7103 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7104 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7105 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7106 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7107 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7108 // this r value looks like a 'dot' particle, fading sharply to
7109 // black at the edges
7110 // (probably not realistic but looks good enough)
7111 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7112 //r = brighten/(range*2+1);
7113 r = brighten / (range * 2 + 1);
7115 r *= (1 - x*x/(float)(range*range));
7116 GL_Color(r, r, r, 1);
7117 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7118 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7119 GL_BlendFunc(GL_ONE, GL_ONE);
7122 // copy the vertically blurred bloom view to a texture
7123 GL_ActiveTexture(0);
7125 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7126 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7129 // apply subtract last
7130 // (just like it would be in a GLSL shader)
7131 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7133 GL_BlendFunc(GL_ONE, GL_ZERO);
7134 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7135 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7136 GL_Color(1, 1, 1, 1);
7137 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7138 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7140 GL_BlendFunc(GL_ONE, GL_ONE);
7141 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7142 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7143 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7144 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7145 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7146 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7147 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7149 // copy the darkened bloom view to a texture
7150 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7151 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7155 void R_HDR_RenderBloomTexture(void)
7157 int oldwidth, oldheight;
7158 float oldcolorscale;
7160 oldcolorscale = r_refdef.view.colorscale;
7161 oldwidth = r_refdef.view.width;
7162 oldheight = r_refdef.view.height;
7163 r_refdef.view.width = r_bloomstate.bloomwidth;
7164 r_refdef.view.height = r_bloomstate.bloomheight;
7166 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
7167 // TODO: add exposure compensation features
7168 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7170 r_refdef.view.showdebug = false;
7171 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7173 R_ResetViewRendering3D();
7175 R_ClearScreen(r_refdef.fogenabled);
7176 if (r_timereport_active)
7177 R_TimeReport("HDRclear");
7180 if (r_timereport_active)
7181 R_TimeReport("visibility");
7183 // only do secondary renders with HDR if r_hdr is 2 or higher
7184 r_waterstate.numwaterplanes = 0;
7185 if (r_waterstate.enabled && r_hdr.integer >= 2)
7186 R_RenderWaterPlanes();
7188 r_refdef.view.showdebug = true;
7190 r_waterstate.numwaterplanes = 0;
7192 R_ResetViewRendering2D();
7194 R_Bloom_CopyHDRTexture();
7195 R_Bloom_MakeTexture();
7197 // restore the view settings
7198 r_refdef.view.width = oldwidth;
7199 r_refdef.view.height = oldheight;
7200 r_refdef.view.colorscale = oldcolorscale;
7201 r_frame++; // used only by R_GetCurrentTexture
7203 R_ResetViewRendering3D();
7205 R_ClearScreen(r_refdef.fogenabled);
7206 if (r_timereport_active)
7207 R_TimeReport("viewclear");
7210 static void R_BlendView(void)
7212 unsigned int permutation;
7213 float uservecs[4][4];
7215 switch (vid.renderpath)
7217 case RENDERPATH_GL20:
7218 case RENDERPATH_CGGL:
7220 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7221 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7222 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7223 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7224 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7226 if (r_bloomstate.texture_screen)
7228 // make sure the buffer is available
7229 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7231 R_ResetViewRendering2D();
7232 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7233 R_Mesh_ColorPointer(NULL, 0, 0);
7235 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7237 // declare variables
7239 static float avgspeed;
7241 speed = VectorLength(cl.movement_velocity);
7243 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7244 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7246 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7247 speed = bound(0, speed, 1);
7248 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7250 // calculate values into a standard alpha
7251 cl.motionbluralpha = 1 - exp(-
7253 (r_motionblur.value * speed / 80)
7255 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7258 max(0.0001, cl.time - cl.oldtime) // fps independent
7261 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7262 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7264 if (cl.motionbluralpha > 0)
7266 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7267 GL_Color(1, 1, 1, cl.motionbluralpha);
7268 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7269 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7270 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7271 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7275 // copy view into the screen texture
7276 R_Mesh_CopyToTexture(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);
7277 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7279 else if (!r_bloomstate.texture_bloom)
7281 // we may still have to do view tint...
7282 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7284 // apply a color tint to the whole view
7285 R_ResetViewRendering2D();
7286 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7287 R_Mesh_ColorPointer(NULL, 0, 0);
7288 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7289 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7290 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7291 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7293 break; // no screen processing, no bloom, skip it
7296 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7298 // render simple bloom effect
7299 // copy the screen and shrink it and darken it for the bloom process
7300 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7301 // make the bloom texture
7302 R_Bloom_MakeTexture();
7305 #if _MSC_VER >= 1400
7306 #define sscanf sscanf_s
7308 memset(uservecs, 0, sizeof(uservecs));
7309 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7310 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7311 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7312 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7314 R_ResetViewRendering2D();
7315 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7316 R_Mesh_ColorPointer(NULL, 0, 0);
7317 GL_Color(1, 1, 1, 1);
7318 GL_BlendFunc(GL_ONE, GL_ZERO);
7319 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7320 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7322 switch(vid.renderpath)
7324 case RENDERPATH_GL20:
7325 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7326 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
7327 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
7328 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7329 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]);
7330 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime , cl.time);
7331 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7332 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]);
7333 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]);
7334 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]);
7335 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]);
7336 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7338 case RENDERPATH_CGGL:
7340 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7341 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
7342 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
7343 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
7344 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
7345 if (r_cg_permutation->fp_ClientTime ) cgGLSetParameter1f( r_cg_permutation->fp_ClientTime , cl.time);CHECKCGERROR
7346 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7347 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
7348 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
7349 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
7350 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
7351 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
7357 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7358 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7360 case RENDERPATH_GL13:
7361 case RENDERPATH_GL11:
7362 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7364 // apply a color tint to the whole view
7365 R_ResetViewRendering2D();
7366 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7367 R_Mesh_ColorPointer(NULL, 0, 0);
7368 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7369 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7370 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7371 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7377 matrix4x4_t r_waterscrollmatrix;
7379 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7381 if (r_refdef.fog_density)
7383 r_refdef.fogcolor[0] = r_refdef.fog_red;
7384 r_refdef.fogcolor[1] = r_refdef.fog_green;
7385 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7387 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7388 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7389 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7390 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7394 VectorCopy(r_refdef.fogcolor, fogvec);
7395 // color.rgb *= ContrastBoost * SceneBrightness;
7396 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7397 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7398 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7399 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7404 void R_UpdateVariables(void)
7408 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7410 r_refdef.farclip = r_farclip_base.value;
7411 if (r_refdef.scene.worldmodel)
7412 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7413 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7415 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7416 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7417 r_refdef.polygonfactor = 0;
7418 r_refdef.polygonoffset = 0;
7419 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7420 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7422 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7423 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7424 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7425 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7426 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7427 if (r_showsurfaces.integer)
7429 r_refdef.scene.rtworld = false;
7430 r_refdef.scene.rtworldshadows = false;
7431 r_refdef.scene.rtdlight = false;
7432 r_refdef.scene.rtdlightshadows = false;
7433 r_refdef.lightmapintensity = 0;
7436 if (gamemode == GAME_NEHAHRA)
7438 if (gl_fogenable.integer)
7440 r_refdef.oldgl_fogenable = true;
7441 r_refdef.fog_density = gl_fogdensity.value;
7442 r_refdef.fog_red = gl_fogred.value;
7443 r_refdef.fog_green = gl_foggreen.value;
7444 r_refdef.fog_blue = gl_fogblue.value;
7445 r_refdef.fog_alpha = 1;
7446 r_refdef.fog_start = 0;
7447 r_refdef.fog_end = gl_skyclip.value;
7448 r_refdef.fog_height = 1<<30;
7449 r_refdef.fog_fadedepth = 128;
7451 else if (r_refdef.oldgl_fogenable)
7453 r_refdef.oldgl_fogenable = false;
7454 r_refdef.fog_density = 0;
7455 r_refdef.fog_red = 0;
7456 r_refdef.fog_green = 0;
7457 r_refdef.fog_blue = 0;
7458 r_refdef.fog_alpha = 0;
7459 r_refdef.fog_start = 0;
7460 r_refdef.fog_end = 0;
7461 r_refdef.fog_height = 1<<30;
7462 r_refdef.fog_fadedepth = 128;
7466 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7467 r_refdef.fog_start = max(0, r_refdef.fog_start);
7468 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7470 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7472 if (r_refdef.fog_density && r_drawfog.integer)
7474 r_refdef.fogenabled = true;
7475 // this is the point where the fog reaches 0.9986 alpha, which we
7476 // consider a good enough cutoff point for the texture
7477 // (0.9986 * 256 == 255.6)
7478 if (r_fog_exp2.integer)
7479 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7481 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7482 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7483 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7484 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7485 // fog color was already set
7486 // update the fog texture
7487 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)
7488 R_BuildFogTexture();
7491 r_refdef.fogenabled = false;
7493 switch(vid.renderpath)
7495 case RENDERPATH_GL20:
7496 case RENDERPATH_CGGL:
7497 if(v_glslgamma.integer && !vid_gammatables_trivial)
7499 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7501 // build GLSL gamma texture
7502 #define RAMPWIDTH 256
7503 unsigned short ramp[RAMPWIDTH * 3];
7504 unsigned char rampbgr[RAMPWIDTH][4];
7507 r_texture_gammaramps_serial = vid_gammatables_serial;
7509 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7510 for(i = 0; i < RAMPWIDTH; ++i)
7512 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7513 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7514 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7517 if (r_texture_gammaramps)
7519 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7523 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);
7529 // remove GLSL gamma texture
7532 case RENDERPATH_GL13:
7533 case RENDERPATH_GL11:
7538 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7539 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7545 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7546 if( scenetype != r_currentscenetype ) {
7547 // store the old scenetype
7548 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7549 r_currentscenetype = scenetype;
7550 // move in the new scene
7551 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7560 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7562 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7563 if( scenetype == r_currentscenetype ) {
7564 return &r_refdef.scene;
7566 return &r_scenes_store[ scenetype ];
7575 void R_RenderView(void)
7577 if (r_timereport_active)
7578 R_TimeReport("start");
7579 r_frame++; // used only by R_GetCurrentTexture
7580 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7582 if (!r_drawentities.integer)
7583 r_refdef.scene.numentities = 0;
7585 R_AnimCache_ClearCache();
7586 R_FrameData_NewFrame();
7588 if (r_refdef.view.isoverlay)
7590 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7591 GL_Clear( GL_DEPTH_BUFFER_BIT );
7592 R_TimeReport("depthclear");
7594 r_refdef.view.showdebug = false;
7596 r_waterstate.enabled = false;
7597 r_waterstate.numwaterplanes = 0;
7605 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7606 return; //Host_Error ("R_RenderView: NULL worldmodel");
7608 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7610 // break apart the view matrix into vectors for various purposes
7611 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7612 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7613 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7614 VectorNegate(r_refdef.view.left, r_refdef.view.right);
7615 // make an inverted copy of the view matrix for tracking sprites
7616 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7618 R_Shadow_UpdateWorldLightSelection();
7620 R_Bloom_StartFrame();
7621 R_Water_StartFrame();
7624 if (r_timereport_active)
7625 R_TimeReport("viewsetup");
7627 R_ResetViewRendering3D();
7629 if (r_refdef.view.clear || r_refdef.fogenabled)
7631 R_ClearScreen(r_refdef.fogenabled);
7632 if (r_timereport_active)
7633 R_TimeReport("viewclear");
7635 r_refdef.view.clear = true;
7637 // this produces a bloom texture to be used in R_BlendView() later
7638 if (r_hdr.integer && r_bloomstate.bloomwidth)
7639 R_HDR_RenderBloomTexture();
7641 r_refdef.view.showdebug = true;
7644 if (r_timereport_active)
7645 R_TimeReport("visibility");
7647 r_waterstate.numwaterplanes = 0;
7648 if (r_waterstate.enabled)
7649 R_RenderWaterPlanes();
7652 r_waterstate.numwaterplanes = 0;
7655 if (r_timereport_active)
7656 R_TimeReport("blendview");
7658 GL_Scissor(0, 0, vid.width, vid.height);
7659 GL_ScissorTest(false);
7663 void R_RenderWaterPlanes(void)
7665 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7667 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7668 if (r_timereport_active)
7669 R_TimeReport("waterworld");
7672 // don't let sound skip if going slow
7673 if (r_refdef.scene.extraupdate)
7676 R_DrawModelsAddWaterPlanes();
7677 if (r_timereport_active)
7678 R_TimeReport("watermodels");
7680 if (r_waterstate.numwaterplanes)
7682 R_Water_ProcessPlanes();
7683 if (r_timereport_active)
7684 R_TimeReport("waterscenes");
7688 extern void R_DrawLightningBeams (void);
7689 extern void VM_CL_AddPolygonsToMeshQueue (void);
7690 extern void R_DrawPortals (void);
7691 extern cvar_t cl_locs_show;
7692 static void R_DrawLocs(void);
7693 static void R_DrawEntityBBoxes(void);
7694 static void R_DrawModelDecals(void);
7695 extern cvar_t cl_decals_newsystem;
7696 extern qboolean r_shadow_usingdeferredprepass;
7697 void R_RenderScene(void)
7699 r_refdef.stats.renders++;
7703 // don't let sound skip if going slow
7704 if (r_refdef.scene.extraupdate)
7707 R_MeshQueue_BeginScene();
7711 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);
7713 if (cl.csqc_vidvars.drawworld)
7715 // don't let sound skip if going slow
7716 if (r_refdef.scene.extraupdate)
7719 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7721 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7722 if (r_timereport_active)
7723 R_TimeReport("worldsky");
7726 if (R_DrawBrushModelsSky() && r_timereport_active)
7727 R_TimeReport("bmodelsky");
7729 if (skyrendermasked && skyrenderlater)
7731 // we have to force off the water clipping plane while rendering sky
7735 if (r_timereport_active)
7736 R_TimeReport("sky");
7740 R_AnimCache_CacheVisibleEntities();
7741 if (r_timereport_active)
7742 R_TimeReport("animation");
7744 R_Shadow_PrepareLights();
7745 if (r_timereport_active)
7746 R_TimeReport("preparelights");
7748 if (r_shadow_usingdeferredprepass)
7749 R_Shadow_DrawPrepass();
7751 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7753 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7754 if (r_timereport_active)
7755 R_TimeReport("worlddepth");
7757 if (r_depthfirst.integer >= 2)
7759 R_DrawModelsDepth();
7760 if (r_timereport_active)
7761 R_TimeReport("modeldepth");
7764 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7766 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7767 if (r_timereport_active)
7768 R_TimeReport("world");
7771 // don't let sound skip if going slow
7772 if (r_refdef.scene.extraupdate)
7776 if (r_timereport_active)
7777 R_TimeReport("models");
7779 // don't let sound skip if going slow
7780 if (r_refdef.scene.extraupdate)
7783 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7785 R_DrawModelShadows();
7786 R_ResetViewRendering3D();
7787 // don't let sound skip if going slow
7788 if (r_refdef.scene.extraupdate)
7792 if (!r_shadow_usingdeferredprepass)
7794 R_Shadow_DrawLights();
7795 if (r_timereport_active)
7796 R_TimeReport("rtlights");
7799 // don't let sound skip if going slow
7800 if (r_refdef.scene.extraupdate)
7803 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7805 R_DrawModelShadows();
7806 R_ResetViewRendering3D();
7807 // don't let sound skip if going slow
7808 if (r_refdef.scene.extraupdate)
7812 if (cl.csqc_vidvars.drawworld)
7814 if (cl_decals_newsystem.integer)
7816 R_DrawModelDecals();
7817 if (r_timereport_active)
7818 R_TimeReport("modeldecals");
7823 if (r_timereport_active)
7824 R_TimeReport("decals");
7828 if (r_timereport_active)
7829 R_TimeReport("particles");
7832 if (r_timereport_active)
7833 R_TimeReport("explosions");
7835 R_DrawLightningBeams();
7836 if (r_timereport_active)
7837 R_TimeReport("lightning");
7840 VM_CL_AddPolygonsToMeshQueue();
7842 if (r_refdef.view.showdebug)
7844 if (cl_locs_show.integer)
7847 if (r_timereport_active)
7848 R_TimeReport("showlocs");
7851 if (r_drawportals.integer)
7854 if (r_timereport_active)
7855 R_TimeReport("portals");
7858 if (r_showbboxes.value > 0)
7860 R_DrawEntityBBoxes();
7861 if (r_timereport_active)
7862 R_TimeReport("bboxes");
7866 R_MeshQueue_RenderTransparent();
7867 if (r_timereport_active)
7868 R_TimeReport("drawtrans");
7870 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))
7872 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7873 if (r_timereport_active)
7874 R_TimeReport("worlddebug");
7875 R_DrawModelsDebug();
7876 if (r_timereport_active)
7877 R_TimeReport("modeldebug");
7880 if (cl.csqc_vidvars.drawworld)
7882 R_Shadow_DrawCoronas();
7883 if (r_timereport_active)
7884 R_TimeReport("coronas");
7887 // don't let sound skip if going slow
7888 if (r_refdef.scene.extraupdate)
7891 R_ResetViewRendering2D();
7894 static const unsigned short bboxelements[36] =
7904 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7907 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7909 RSurf_ActiveWorldEntity();
7911 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7912 GL_DepthMask(false);
7913 GL_DepthRange(0, 1);
7914 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7915 R_Mesh_ResetTextureState();
7917 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7918 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7919 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7920 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7921 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7922 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7923 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7924 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7925 R_FillColors(color4f, 8, cr, cg, cb, ca);
7926 if (r_refdef.fogenabled)
7928 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7930 f1 = RSurf_FogVertex(v);
7932 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7933 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7934 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7937 R_Mesh_VertexPointer(vertex3f, 0, 0);
7938 R_Mesh_ColorPointer(color4f, 0, 0);
7939 R_Mesh_ResetTextureState();
7940 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7941 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
7944 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7948 prvm_edict_t *edict;
7949 prvm_prog_t *prog_save = prog;
7951 // this function draws bounding boxes of server entities
7955 GL_CullFace(GL_NONE);
7956 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7960 for (i = 0;i < numsurfaces;i++)
7962 edict = PRVM_EDICT_NUM(surfacelist[i]);
7963 switch ((int)edict->fields.server->solid)
7965 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7966 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7967 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7968 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7969 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7970 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7972 color[3] *= r_showbboxes.value;
7973 color[3] = bound(0, color[3], 1);
7974 GL_DepthTest(!r_showdisabledepthtest.integer);
7975 GL_CullFace(r_refdef.view.cullface_front);
7976 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7982 static void R_DrawEntityBBoxes(void)
7985 prvm_edict_t *edict;
7987 prvm_prog_t *prog_save = prog;
7989 // this function draws bounding boxes of server entities
7995 for (i = 0;i < prog->num_edicts;i++)
7997 edict = PRVM_EDICT_NUM(i);
7998 if (edict->priv.server->free)
8000 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8001 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8003 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8005 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8006 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8012 static const int nomodelelement3i[24] =
8024 static const unsigned short nomodelelement3s[24] =
8036 static const float nomodelvertex3f[6*3] =
8046 static const float nomodelcolor4f[6*4] =
8048 0.0f, 0.0f, 0.5f, 1.0f,
8049 0.0f, 0.0f, 0.5f, 1.0f,
8050 0.0f, 0.5f, 0.0f, 1.0f,
8051 0.0f, 0.5f, 0.0f, 1.0f,
8052 0.5f, 0.0f, 0.0f, 1.0f,
8053 0.5f, 0.0f, 0.0f, 1.0f
8056 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8062 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);
8064 // this is only called once per entity so numsurfaces is always 1, and
8065 // surfacelist is always {0}, so this code does not handle batches
8067 if (rsurface.ent_flags & RENDER_ADDITIVE)
8069 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8070 GL_DepthMask(false);
8072 else if (rsurface.colormod[3] < 1)
8074 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8075 GL_DepthMask(false);
8079 GL_BlendFunc(GL_ONE, GL_ZERO);
8082 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8083 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8084 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8085 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8086 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8087 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8088 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8089 R_Mesh_ColorPointer(color4f, 0, 0);
8090 for (i = 0, c = color4f;i < 6;i++, c += 4)
8092 c[0] *= rsurface.colormod[0];
8093 c[1] *= rsurface.colormod[1];
8094 c[2] *= rsurface.colormod[2];
8095 c[3] *= rsurface.colormod[3];
8097 if (r_refdef.fogenabled)
8099 for (i = 0, c = color4f;i < 6;i++, c += 4)
8101 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8103 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8104 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8105 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8108 R_Mesh_ResetTextureState();
8109 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8112 void R_DrawNoModel(entity_render_t *ent)
8115 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8116 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8117 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8119 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8122 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8124 vec3_t right1, right2, diff, normal;
8126 VectorSubtract (org2, org1, normal);
8128 // calculate 'right' vector for start
8129 VectorSubtract (r_refdef.view.origin, org1, diff);
8130 CrossProduct (normal, diff, right1);
8131 VectorNormalize (right1);
8133 // calculate 'right' vector for end
8134 VectorSubtract (r_refdef.view.origin, org2, diff);
8135 CrossProduct (normal, diff, right2);
8136 VectorNormalize (right2);
8138 vert[ 0] = org1[0] + width * right1[0];
8139 vert[ 1] = org1[1] + width * right1[1];
8140 vert[ 2] = org1[2] + width * right1[2];
8141 vert[ 3] = org1[0] - width * right1[0];
8142 vert[ 4] = org1[1] - width * right1[1];
8143 vert[ 5] = org1[2] - width * right1[2];
8144 vert[ 6] = org2[0] - width * right2[0];
8145 vert[ 7] = org2[1] - width * right2[1];
8146 vert[ 8] = org2[2] - width * right2[2];
8147 vert[ 9] = org2[0] + width * right2[0];
8148 vert[10] = org2[1] + width * right2[1];
8149 vert[11] = org2[2] + width * right2[2];
8152 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)
8154 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8155 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8156 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8157 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8158 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8159 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8160 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8161 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8162 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8163 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8164 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8165 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8168 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8173 VectorSet(v, x, y, z);
8174 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8175 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8177 if (i == mesh->numvertices)
8179 if (mesh->numvertices < mesh->maxvertices)
8181 VectorCopy(v, vertex3f);
8182 mesh->numvertices++;
8184 return mesh->numvertices;
8190 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8194 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8195 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8196 e = mesh->element3i + mesh->numtriangles * 3;
8197 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8199 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8200 if (mesh->numtriangles < mesh->maxtriangles)
8205 mesh->numtriangles++;
8207 element[1] = element[2];
8211 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8215 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8216 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8217 e = mesh->element3i + mesh->numtriangles * 3;
8218 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8220 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8221 if (mesh->numtriangles < mesh->maxtriangles)
8226 mesh->numtriangles++;
8228 element[1] = element[2];
8232 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8233 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8235 int planenum, planenum2;
8238 mplane_t *plane, *plane2;
8240 double temppoints[2][256*3];
8241 // figure out how large a bounding box we need to properly compute this brush
8243 for (w = 0;w < numplanes;w++)
8244 maxdist = max(maxdist, fabs(planes[w].dist));
8245 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8246 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8247 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8251 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8252 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8254 if (planenum2 == planenum)
8256 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);
8259 if (tempnumpoints < 3)
8261 // generate elements forming a triangle fan for this polygon
8262 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8266 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)
8268 texturelayer_t *layer;
8269 layer = t->currentlayers + t->currentnumlayers++;
8271 layer->depthmask = depthmask;
8272 layer->blendfunc1 = blendfunc1;
8273 layer->blendfunc2 = blendfunc2;
8274 layer->texture = texture;
8275 layer->texmatrix = *matrix;
8276 layer->color[0] = r;
8277 layer->color[1] = g;
8278 layer->color[2] = b;
8279 layer->color[3] = a;
8282 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8285 index = parms[2] + r_refdef.scene.time * parms[3];
8286 index -= floor(index);
8290 case Q3WAVEFUNC_NONE:
8291 case Q3WAVEFUNC_NOISE:
8292 case Q3WAVEFUNC_COUNT:
8295 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8296 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8297 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8298 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8299 case Q3WAVEFUNC_TRIANGLE:
8301 f = index - floor(index);
8312 return (float)(parms[0] + parms[1] * f);
8315 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8320 matrix4x4_t matrix, temp;
8321 switch(tcmod->tcmod)
8325 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8326 matrix = r_waterscrollmatrix;
8328 matrix = identitymatrix;
8330 case Q3TCMOD_ENTITYTRANSLATE:
8331 // this is used in Q3 to allow the gamecode to control texcoord
8332 // scrolling on the entity, which is not supported in darkplaces yet.
8333 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8335 case Q3TCMOD_ROTATE:
8336 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8337 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8338 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8341 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8343 case Q3TCMOD_SCROLL:
8344 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8346 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8347 w = (int) tcmod->parms[0];
8348 h = (int) tcmod->parms[1];
8349 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8351 idx = (int) floor(f * w * h);
8352 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8354 case Q3TCMOD_STRETCH:
8355 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8356 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8358 case Q3TCMOD_TRANSFORM:
8359 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8360 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8361 VectorSet(tcmat + 6, 0 , 0 , 1);
8362 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8363 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8365 case Q3TCMOD_TURBULENT:
8366 // this is handled in the RSurf_PrepareVertices function
8367 matrix = identitymatrix;
8371 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8374 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8376 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8377 char name[MAX_QPATH];
8378 skinframe_t *skinframe;
8379 unsigned char pixels[296*194];
8380 strlcpy(cache->name, skinname, sizeof(cache->name));
8381 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8382 if (developer_loading.integer)
8383 Con_Printf("loading %s\n", name);
8384 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8385 if (!skinframe || !skinframe->base)
8388 fs_offset_t filesize;
8390 f = FS_LoadFile(name, tempmempool, true, &filesize);
8393 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8394 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8398 cache->skinframe = skinframe;
8401 texture_t *R_GetCurrentTexture(texture_t *t)
8404 const entity_render_t *ent = rsurface.entity;
8405 dp_model_t *model = ent->model;
8406 q3shaderinfo_layer_tcmod_t *tcmod;
8408 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
8409 return t->currentframe;
8410 t->update_lastrenderframe = r_frame;
8411 t->update_lastrenderentity = (void *)ent;
8413 // switch to an alternate material if this is a q1bsp animated material
8415 texture_t *texture = t;
8416 int s = rsurface.ent_skinnum;
8417 if ((unsigned int)s >= (unsigned int)model->numskins)
8419 if (model->skinscenes)
8421 if (model->skinscenes[s].framecount > 1)
8422 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8424 s = model->skinscenes[s].firstframe;
8427 t = t + s * model->num_surfaces;
8430 // use an alternate animation if the entity's frame is not 0,
8431 // and only if the texture has an alternate animation
8432 if (rsurface.ent_alttextures && t->anim_total[1])
8433 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8435 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8437 texture->currentframe = t;
8440 // update currentskinframe to be a qw skin or animation frame
8441 if (rsurface.ent_qwskin >= 0)
8443 i = rsurface.ent_qwskin;
8444 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8446 r_qwskincache_size = cl.maxclients;
8448 Mem_Free(r_qwskincache);
8449 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8451 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8452 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8453 t->currentskinframe = r_qwskincache[i].skinframe;
8454 if (t->currentskinframe == NULL)
8455 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8457 else if (t->numskinframes >= 2)
8458 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8459 if (t->backgroundnumskinframes >= 2)
8460 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8462 t->currentmaterialflags = t->basematerialflags;
8463 t->currentalpha = rsurface.colormod[3];
8464 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8465 t->currentalpha *= r_wateralpha.value;
8466 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8467 t->currentalpha *= t->r_water_wateralpha;
8468 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8469 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8470 if (!(rsurface.ent_flags & RENDER_LIGHT))
8471 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8472 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8474 // pick a model lighting mode
8475 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8476 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8478 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8480 if (rsurface.ent_flags & RENDER_ADDITIVE)
8481 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8482 else if (t->currentalpha < 1)
8483 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8484 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8485 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8486 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8487 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8488 if (t->backgroundnumskinframes)
8489 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8490 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8492 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8493 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8496 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8497 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8498 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8500 // there is no tcmod
8501 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8503 t->currenttexmatrix = r_waterscrollmatrix;
8504 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8506 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8508 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8509 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8512 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8513 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8514 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8515 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8517 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8518 if (t->currentskinframe->qpixels)
8519 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8520 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8521 if (!t->basetexture)
8522 t->basetexture = r_texture_notexture;
8523 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8524 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8525 t->nmaptexture = t->currentskinframe->nmap;
8526 if (!t->nmaptexture)
8527 t->nmaptexture = r_texture_blanknormalmap;
8528 t->glosstexture = r_texture_black;
8529 t->glowtexture = t->currentskinframe->glow;
8530 t->fogtexture = t->currentskinframe->fog;
8531 if (t->backgroundnumskinframes)
8533 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8534 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8535 t->backgroundglosstexture = r_texture_black;
8536 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8537 if (!t->backgroundnmaptexture)
8538 t->backgroundnmaptexture = r_texture_blanknormalmap;
8542 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8543 t->backgroundnmaptexture = r_texture_blanknormalmap;
8544 t->backgroundglosstexture = r_texture_black;
8545 t->backgroundglowtexture = NULL;
8547 t->specularpower = r_shadow_glossexponent.value;
8548 // TODO: store reference values for these in the texture?
8549 t->specularscale = 0;
8550 if (r_shadow_gloss.integer > 0)
8552 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8554 if (r_shadow_glossintensity.value > 0)
8556 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8557 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8558 t->specularscale = r_shadow_glossintensity.value;
8561 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8563 t->glosstexture = r_texture_white;
8564 t->backgroundglosstexture = r_texture_white;
8565 t->specularscale = r_shadow_gloss2intensity.value;
8566 t->specularpower = r_shadow_gloss2exponent.value;
8569 t->specularscale *= t->specularscalemod;
8570 t->specularpower *= t->specularpowermod;
8572 // lightmaps mode looks bad with dlights using actual texturing, so turn
8573 // off the colormap and glossmap, but leave the normalmap on as it still
8574 // accurately represents the shading involved
8575 if (gl_lightmaps.integer)
8577 t->basetexture = r_texture_grey128;
8578 t->pantstexture = r_texture_black;
8579 t->shirttexture = r_texture_black;
8580 t->nmaptexture = r_texture_blanknormalmap;
8581 t->glosstexture = r_texture_black;
8582 t->glowtexture = NULL;
8583 t->fogtexture = NULL;
8584 t->backgroundbasetexture = NULL;
8585 t->backgroundnmaptexture = r_texture_blanknormalmap;
8586 t->backgroundglosstexture = r_texture_black;
8587 t->backgroundglowtexture = NULL;
8588 t->specularscale = 0;
8589 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8592 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8593 VectorClear(t->dlightcolor);
8594 t->currentnumlayers = 0;
8595 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8597 int blendfunc1, blendfunc2;
8599 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8601 blendfunc1 = GL_SRC_ALPHA;
8602 blendfunc2 = GL_ONE;
8604 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8606 blendfunc1 = GL_SRC_ALPHA;
8607 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8609 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8611 blendfunc1 = t->customblendfunc[0];
8612 blendfunc2 = t->customblendfunc[1];
8616 blendfunc1 = GL_ONE;
8617 blendfunc2 = GL_ZERO;
8619 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8620 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8622 // fullbright is not affected by r_refdef.lightmapintensity
8623 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]);
8624 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8625 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]);
8626 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8627 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]);
8631 vec3_t ambientcolor;
8633 // set the color tint used for lights affecting this surface
8634 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8636 // q3bsp has no lightmap updates, so the lightstylevalue that
8637 // would normally be baked into the lightmap must be
8638 // applied to the color
8639 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8640 if (model->type == mod_brushq3)
8641 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8642 colorscale *= r_refdef.lightmapintensity;
8643 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8644 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8645 // basic lit geometry
8646 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]);
8647 // add pants/shirt if needed
8648 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8649 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]);
8650 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8651 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]);
8652 // now add ambient passes if needed
8653 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8655 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]);
8656 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8657 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]);
8658 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8659 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]);
8662 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8663 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]);
8664 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8666 // if this is opaque use alpha blend which will darken the earlier
8669 // if this is an alpha blended material, all the earlier passes
8670 // were darkened by fog already, so we only need to add the fog
8671 // color ontop through the fog mask texture
8673 // if this is an additive blended material, all the earlier passes
8674 // were darkened by fog already, and we should not add fog color
8675 // (because the background was not darkened, there is no fog color
8676 // that was lost behind it).
8677 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]);
8681 return t->currentframe;
8684 rsurfacestate_t rsurface;
8686 void R_Mesh_ResizeArrays(int newvertices)
8689 if (rsurface.array_size >= newvertices)
8691 if (rsurface.array_modelvertex3f)
8692 Mem_Free(rsurface.array_modelvertex3f);
8693 rsurface.array_size = (newvertices + 1023) & ~1023;
8694 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8695 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
8696 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
8697 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
8698 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
8699 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
8700 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8701 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8702 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
8703 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
8704 rsurface.array_color4f = base + rsurface.array_size * 27;
8705 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8708 void RSurf_ActiveWorldEntity(void)
8710 dp_model_t *model = r_refdef.scene.worldmodel;
8711 //if (rsurface.entity == r_refdef.scene.worldentity)
8713 rsurface.entity = r_refdef.scene.worldentity;
8714 rsurface.skeleton = NULL;
8715 rsurface.ent_skinnum = 0;
8716 rsurface.ent_qwskin = -1;
8717 rsurface.ent_shadertime = 0;
8718 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8719 if (rsurface.array_size < model->surfmesh.num_vertices)
8720 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8721 rsurface.matrix = identitymatrix;
8722 rsurface.inversematrix = identitymatrix;
8723 rsurface.matrixscale = 1;
8724 rsurface.inversematrixscale = 1;
8725 R_EntityMatrix(&identitymatrix);
8726 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8727 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8728 rsurface.fograngerecip = r_refdef.fograngerecip;
8729 rsurface.fogheightfade = r_refdef.fogheightfade;
8730 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8731 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8732 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8733 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8734 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8735 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8736 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8737 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8738 rsurface.colormod[3] = 1;
8739 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);
8740 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8741 rsurface.frameblend[0].lerp = 1;
8742 rsurface.ent_alttextures = false;
8743 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8744 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8745 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8746 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8747 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8748 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8749 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8750 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8751 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8752 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8753 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8754 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8755 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8756 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8757 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8758 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8759 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8760 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8761 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8762 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8763 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8764 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8765 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8766 rsurface.modelelement3i = model->surfmesh.data_element3i;
8767 rsurface.modelelement3s = model->surfmesh.data_element3s;
8768 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8769 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8770 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8771 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8772 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8773 rsurface.modelsurfaces = model->data_surfaces;
8774 rsurface.generatedvertex = false;
8775 rsurface.vertex3f = rsurface.modelvertex3f;
8776 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8777 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8778 rsurface.svector3f = rsurface.modelsvector3f;
8779 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8780 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8781 rsurface.tvector3f = rsurface.modeltvector3f;
8782 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8783 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8784 rsurface.normal3f = rsurface.modelnormal3f;
8785 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8786 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8787 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8790 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8792 dp_model_t *model = ent->model;
8793 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8795 rsurface.entity = (entity_render_t *)ent;
8796 rsurface.skeleton = ent->skeleton;
8797 rsurface.ent_skinnum = ent->skinnum;
8798 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;
8799 rsurface.ent_shadertime = ent->shadertime;
8800 rsurface.ent_flags = ent->flags;
8801 if (rsurface.array_size < model->surfmesh.num_vertices)
8802 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8803 rsurface.matrix = ent->matrix;
8804 rsurface.inversematrix = ent->inversematrix;
8805 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8806 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8807 R_EntityMatrix(&rsurface.matrix);
8808 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8809 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8810 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8811 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8812 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8813 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8814 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8815 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8816 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8817 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8818 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8819 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8820 rsurface.colormod[3] = ent->alpha;
8821 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8822 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8823 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8824 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8825 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8826 if (ent->model->brush.submodel && !prepass)
8828 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8829 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8831 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8833 if (ent->animcache_vertex3f && !r_framedata_failed)
8835 rsurface.modelvertex3f = ent->animcache_vertex3f;
8836 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8837 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8838 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8840 else if (wanttangents)
8842 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8843 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
8844 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
8845 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8846 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
8848 else if (wantnormals)
8850 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8851 rsurface.modelsvector3f = NULL;
8852 rsurface.modeltvector3f = NULL;
8853 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8854 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
8858 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8859 rsurface.modelsvector3f = NULL;
8860 rsurface.modeltvector3f = NULL;
8861 rsurface.modelnormal3f = NULL;
8862 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
8864 rsurface.modelvertex3f_bufferobject = 0;
8865 rsurface.modelvertex3f_bufferoffset = 0;
8866 rsurface.modelsvector3f_bufferobject = 0;
8867 rsurface.modelsvector3f_bufferoffset = 0;
8868 rsurface.modeltvector3f_bufferobject = 0;
8869 rsurface.modeltvector3f_bufferoffset = 0;
8870 rsurface.modelnormal3f_bufferobject = 0;
8871 rsurface.modelnormal3f_bufferoffset = 0;
8872 rsurface.generatedvertex = true;
8876 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8877 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8878 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8879 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8880 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8881 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8882 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8883 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8884 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8885 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8886 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8887 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8888 rsurface.generatedvertex = false;
8890 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8891 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8892 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8893 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8894 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8895 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8896 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8897 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8898 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8899 rsurface.modelelement3i = model->surfmesh.data_element3i;
8900 rsurface.modelelement3s = model->surfmesh.data_element3s;
8901 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8902 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8903 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8904 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8905 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8906 rsurface.modelsurfaces = model->data_surfaces;
8907 rsurface.vertex3f = rsurface.modelvertex3f;
8908 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8909 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8910 rsurface.svector3f = rsurface.modelsvector3f;
8911 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8912 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8913 rsurface.tvector3f = rsurface.modeltvector3f;
8914 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8915 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8916 rsurface.normal3f = rsurface.modelnormal3f;
8917 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8918 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8919 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8922 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)
8924 rsurface.entity = r_refdef.scene.worldentity;
8925 rsurface.skeleton = NULL;
8926 rsurface.ent_skinnum = 0;
8927 rsurface.ent_qwskin = -1;
8928 rsurface.ent_shadertime = shadertime;
8929 rsurface.ent_flags = entflags;
8930 rsurface.modelnum_vertices = numvertices;
8931 rsurface.modelnum_triangles = numtriangles;
8932 if (rsurface.array_size < rsurface.modelnum_vertices)
8933 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
8934 rsurface.matrix = *matrix;
8935 rsurface.inversematrix = *inversematrix;
8936 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8937 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8938 R_EntityMatrix(&rsurface.matrix);
8939 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8940 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8941 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8942 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8943 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8944 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8945 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8946 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8947 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8948 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8949 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8950 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8951 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);
8952 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8953 rsurface.frameblend[0].lerp = 1;
8954 rsurface.ent_alttextures = false;
8955 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8956 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8959 rsurface.modelvertex3f = vertex3f;
8960 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
8961 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
8962 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8964 else if (wantnormals)
8966 rsurface.modelvertex3f = vertex3f;
8967 rsurface.modelsvector3f = NULL;
8968 rsurface.modeltvector3f = NULL;
8969 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8973 rsurface.modelvertex3f = vertex3f;
8974 rsurface.modelsvector3f = NULL;
8975 rsurface.modeltvector3f = NULL;
8976 rsurface.modelnormal3f = NULL;
8978 rsurface.modelvertex3f_bufferobject = 0;
8979 rsurface.modelvertex3f_bufferoffset = 0;
8980 rsurface.modelsvector3f_bufferobject = 0;
8981 rsurface.modelsvector3f_bufferoffset = 0;
8982 rsurface.modeltvector3f_bufferobject = 0;
8983 rsurface.modeltvector3f_bufferoffset = 0;
8984 rsurface.modelnormal3f_bufferobject = 0;
8985 rsurface.modelnormal3f_bufferoffset = 0;
8986 rsurface.generatedvertex = true;
8987 rsurface.modellightmapcolor4f = color4f;
8988 rsurface.modellightmapcolor4f_bufferobject = 0;
8989 rsurface.modellightmapcolor4f_bufferoffset = 0;
8990 rsurface.modeltexcoordtexture2f = texcoord2f;
8991 rsurface.modeltexcoordtexture2f_bufferobject = 0;
8992 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8993 rsurface.modeltexcoordlightmap2f = NULL;
8994 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
8995 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8996 rsurface.modelelement3i = element3i;
8997 rsurface.modelelement3s = element3s;
8998 rsurface.modelelement3i_bufferobject = 0;
8999 rsurface.modelelement3s_bufferobject = 0;
9000 rsurface.modellightmapoffsets = NULL;
9001 rsurface.modelsurfaces = NULL;
9002 rsurface.vertex3f = rsurface.modelvertex3f;
9003 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9004 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9005 rsurface.svector3f = rsurface.modelsvector3f;
9006 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9007 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9008 rsurface.tvector3f = rsurface.modeltvector3f;
9009 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9010 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9011 rsurface.normal3f = rsurface.modelnormal3f;
9012 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9013 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9014 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9016 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9018 if ((wantnormals || wanttangents) && !normal3f)
9019 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9020 if (wanttangents && !svector3f)
9021 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);
9025 float RSurf_FogPoint(const float *v)
9027 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9028 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9029 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9030 float FogHeightFade = r_refdef.fogheightfade;
9032 unsigned int fogmasktableindex;
9033 if (r_refdef.fogplaneviewabove)
9034 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9036 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9037 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9038 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9041 float RSurf_FogVertex(const float *v)
9043 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9044 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9045 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9046 float FogHeightFade = rsurface.fogheightfade;
9048 unsigned int fogmasktableindex;
9049 if (r_refdef.fogplaneviewabove)
9050 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9052 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9053 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9054 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9057 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9058 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9061 int texturesurfaceindex;
9066 const float *v1, *in_tc;
9068 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9070 q3shaderinfo_deform_t *deform;
9071 // 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
9072 if (rsurface.generatedvertex)
9074 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9075 generatenormals = true;
9076 for (i = 0;i < Q3MAXDEFORMS;i++)
9078 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9080 generatetangents = true;
9081 generatenormals = true;
9083 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9084 generatenormals = true;
9086 if (generatenormals && !rsurface.modelnormal3f)
9088 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9089 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9090 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9091 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9093 if (generatetangents && !rsurface.modelsvector3f)
9095 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9096 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9097 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9098 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9099 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9100 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9101 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);
9104 rsurface.vertex3f = rsurface.modelvertex3f;
9105 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9106 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9107 rsurface.svector3f = rsurface.modelsvector3f;
9108 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9109 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9110 rsurface.tvector3f = rsurface.modeltvector3f;
9111 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9112 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9113 rsurface.normal3f = rsurface.modelnormal3f;
9114 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9115 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9116 // if vertices are deformed (sprite flares and things in maps, possibly
9117 // water waves, bulges and other deformations), generate them into
9118 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9119 // (may be static model data or generated data for an animated model, or
9120 // the previous deform pass)
9121 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9123 switch (deform->deform)
9126 case Q3DEFORM_PROJECTIONSHADOW:
9127 case Q3DEFORM_TEXT0:
9128 case Q3DEFORM_TEXT1:
9129 case Q3DEFORM_TEXT2:
9130 case Q3DEFORM_TEXT3:
9131 case Q3DEFORM_TEXT4:
9132 case Q3DEFORM_TEXT5:
9133 case Q3DEFORM_TEXT6:
9134 case Q3DEFORM_TEXT7:
9137 case Q3DEFORM_AUTOSPRITE:
9138 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9139 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9140 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9141 VectorNormalize(newforward);
9142 VectorNormalize(newright);
9143 VectorNormalize(newup);
9144 // make deformed versions of only the model vertices used by the specified surfaces
9145 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9147 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9148 // a single autosprite surface can contain multiple sprites...
9149 for (j = 0;j < surface->num_vertices - 3;j += 4)
9151 VectorClear(center);
9152 for (i = 0;i < 4;i++)
9153 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9154 VectorScale(center, 0.25f, center);
9155 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9156 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9157 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9158 for (i = 0;i < 4;i++)
9160 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9161 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9164 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);
9165 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);
9167 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9168 rsurface.vertex3f_bufferobject = 0;
9169 rsurface.vertex3f_bufferoffset = 0;
9170 rsurface.svector3f = rsurface.array_deformedsvector3f;
9171 rsurface.svector3f_bufferobject = 0;
9172 rsurface.svector3f_bufferoffset = 0;
9173 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9174 rsurface.tvector3f_bufferobject = 0;
9175 rsurface.tvector3f_bufferoffset = 0;
9176 rsurface.normal3f = rsurface.array_deformednormal3f;
9177 rsurface.normal3f_bufferobject = 0;
9178 rsurface.normal3f_bufferoffset = 0;
9180 case Q3DEFORM_AUTOSPRITE2:
9181 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9182 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9183 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9184 VectorNormalize(newforward);
9185 VectorNormalize(newright);
9186 VectorNormalize(newup);
9187 // make deformed versions of only the model vertices used by the specified surfaces
9188 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9190 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9191 const float *v1, *v2;
9201 memset(shortest, 0, sizeof(shortest));
9202 // a single autosprite surface can contain multiple sprites...
9203 for (j = 0;j < surface->num_vertices - 3;j += 4)
9205 VectorClear(center);
9206 for (i = 0;i < 4;i++)
9207 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9208 VectorScale(center, 0.25f, center);
9209 // find the two shortest edges, then use them to define the
9210 // axis vectors for rotating around the central axis
9211 for (i = 0;i < 6;i++)
9213 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9214 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9216 Debug_PolygonBegin(NULL, 0);
9217 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9218 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);
9219 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9222 l = VectorDistance2(v1, v2);
9223 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9225 l += (1.0f / 1024.0f);
9226 if (shortest[0].length2 > l || i == 0)
9228 shortest[1] = shortest[0];
9229 shortest[0].length2 = l;
9230 shortest[0].v1 = v1;
9231 shortest[0].v2 = v2;
9233 else if (shortest[1].length2 > l || i == 1)
9235 shortest[1].length2 = l;
9236 shortest[1].v1 = v1;
9237 shortest[1].v2 = v2;
9240 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9241 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9243 Debug_PolygonBegin(NULL, 0);
9244 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9245 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);
9246 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9249 // this calculates the right vector from the shortest edge
9250 // and the up vector from the edge midpoints
9251 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9252 VectorNormalize(right);
9253 VectorSubtract(end, start, up);
9254 VectorNormalize(up);
9255 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9256 VectorSubtract(rsurface.localvieworigin, center, forward);
9257 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9258 VectorNegate(forward, forward);
9259 VectorReflect(forward, 0, up, forward);
9260 VectorNormalize(forward);
9261 CrossProduct(up, forward, newright);
9262 VectorNormalize(newright);
9264 Debug_PolygonBegin(NULL, 0);
9265 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);
9266 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9267 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9271 Debug_PolygonBegin(NULL, 0);
9272 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9273 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9274 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9277 // rotate the quad around the up axis vector, this is made
9278 // especially easy by the fact we know the quad is flat,
9279 // so we only have to subtract the center position and
9280 // measure distance along the right vector, and then
9281 // multiply that by the newright vector and add back the
9283 // we also need to subtract the old position to undo the
9284 // displacement from the center, which we do with a
9285 // DotProduct, the subtraction/addition of center is also
9286 // optimized into DotProducts here
9287 l = DotProduct(right, center);
9288 for (i = 0;i < 4;i++)
9290 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9291 f = DotProduct(right, v1) - l;
9292 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9295 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);
9296 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);
9298 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9299 rsurface.vertex3f_bufferobject = 0;
9300 rsurface.vertex3f_bufferoffset = 0;
9301 rsurface.svector3f = rsurface.array_deformedsvector3f;
9302 rsurface.svector3f_bufferobject = 0;
9303 rsurface.svector3f_bufferoffset = 0;
9304 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9305 rsurface.tvector3f_bufferobject = 0;
9306 rsurface.tvector3f_bufferoffset = 0;
9307 rsurface.normal3f = rsurface.array_deformednormal3f;
9308 rsurface.normal3f_bufferobject = 0;
9309 rsurface.normal3f_bufferoffset = 0;
9311 case Q3DEFORM_NORMAL:
9312 // deform the normals to make reflections wavey
9313 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9315 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9316 for (j = 0;j < surface->num_vertices;j++)
9319 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9320 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9321 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9322 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9323 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9324 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9325 VectorNormalize(normal);
9327 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);
9329 rsurface.svector3f = rsurface.array_deformedsvector3f;
9330 rsurface.svector3f_bufferobject = 0;
9331 rsurface.svector3f_bufferoffset = 0;
9332 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9333 rsurface.tvector3f_bufferobject = 0;
9334 rsurface.tvector3f_bufferoffset = 0;
9335 rsurface.normal3f = rsurface.array_deformednormal3f;
9336 rsurface.normal3f_bufferobject = 0;
9337 rsurface.normal3f_bufferoffset = 0;
9340 // deform vertex array to make wavey water and flags and such
9341 waveparms[0] = deform->waveparms[0];
9342 waveparms[1] = deform->waveparms[1];
9343 waveparms[2] = deform->waveparms[2];
9344 waveparms[3] = deform->waveparms[3];
9345 // this is how a divisor of vertex influence on deformation
9346 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9347 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9348 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9350 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9351 for (j = 0;j < surface->num_vertices;j++)
9353 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
9354 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
9355 // if the wavefunc depends on time, evaluate it per-vertex
9358 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9359 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9361 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
9364 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9365 rsurface.vertex3f_bufferobject = 0;
9366 rsurface.vertex3f_bufferoffset = 0;
9368 case Q3DEFORM_BULGE:
9369 // deform vertex array to make the surface have moving bulges
9370 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9372 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9373 for (j = 0;j < surface->num_vertices;j++)
9375 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9376 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9379 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9380 rsurface.vertex3f_bufferobject = 0;
9381 rsurface.vertex3f_bufferoffset = 0;
9384 // deform vertex array
9385 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9386 VectorScale(deform->parms, scale, waveparms);
9387 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9389 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9390 for (j = 0;j < surface->num_vertices;j++)
9391 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9393 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9394 rsurface.vertex3f_bufferobject = 0;
9395 rsurface.vertex3f_bufferoffset = 0;
9399 // generate texcoords based on the chosen texcoord source
9400 switch(rsurface.texture->tcgen.tcgen)
9403 case Q3TCGEN_TEXTURE:
9404 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9405 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
9406 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9408 case Q3TCGEN_LIGHTMAP:
9409 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
9410 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9411 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9413 case Q3TCGEN_VECTOR:
9414 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9416 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9417 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)
9419 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9420 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9423 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9424 rsurface.texcoordtexture2f_bufferobject = 0;
9425 rsurface.texcoordtexture2f_bufferoffset = 0;
9427 case Q3TCGEN_ENVIRONMENT:
9428 // make environment reflections using a spheremap
9429 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9431 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9432 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9433 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9434 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9435 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9437 // identical to Q3A's method, but executed in worldspace so
9438 // carried models can be shiny too
9440 float viewer[3], d, reflected[3], worldreflected[3];
9442 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9443 // VectorNormalize(viewer);
9445 d = DotProduct(normal, viewer);
9447 reflected[0] = normal[0]*2*d - viewer[0];
9448 reflected[1] = normal[1]*2*d - viewer[1];
9449 reflected[2] = normal[2]*2*d - viewer[2];
9450 // note: this is proportinal to viewer, so we can normalize later
9452 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9453 VectorNormalize(worldreflected);
9455 // note: this sphere map only uses world x and z!
9456 // so positive and negative y will LOOK THE SAME.
9457 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9458 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9461 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9462 rsurface.texcoordtexture2f_bufferobject = 0;
9463 rsurface.texcoordtexture2f_bufferoffset = 0;
9466 // the only tcmod that needs software vertex processing is turbulent, so
9467 // check for it here and apply the changes if needed
9468 // and we only support that as the first one
9469 // (handling a mixture of turbulent and other tcmods would be problematic
9470 // without punting it entirely to a software path)
9471 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9473 amplitude = rsurface.texture->tcmods[0].parms[1];
9474 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9475 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9477 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9478 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)
9480 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9481 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9484 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9485 rsurface.texcoordtexture2f_bufferobject = 0;
9486 rsurface.texcoordtexture2f_bufferoffset = 0;
9488 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9489 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9490 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9491 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9494 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9497 const msurface_t *surface = texturesurfacelist[0];
9498 const msurface_t *surface2;
9503 // TODO: lock all array ranges before render, rather than on each surface
9504 if (texturenumsurfaces == 1)
9506 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9507 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);
9509 else if (r_batchmode.integer == 2)
9511 #define MAXBATCHTRIANGLES 4096
9512 int batchtriangles = 0;
9513 static int batchelements[MAXBATCHTRIANGLES*3];
9514 for (i = 0;i < texturenumsurfaces;i = j)
9516 surface = texturesurfacelist[i];
9518 if (surface->num_triangles > MAXBATCHTRIANGLES)
9520 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);
9523 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9524 batchtriangles = surface->num_triangles;
9525 firstvertex = surface->num_firstvertex;
9526 endvertex = surface->num_firstvertex + surface->num_vertices;
9527 for (;j < texturenumsurfaces;j++)
9529 surface2 = texturesurfacelist[j];
9530 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9532 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9533 batchtriangles += surface2->num_triangles;
9534 firstvertex = min(firstvertex, surface2->num_firstvertex);
9535 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9537 surface2 = texturesurfacelist[j-1];
9538 numvertices = endvertex - firstvertex;
9539 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9542 else if (r_batchmode.integer == 1)
9544 for (i = 0;i < texturenumsurfaces;i = j)
9546 surface = texturesurfacelist[i];
9547 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9548 if (texturesurfacelist[j] != surface2)
9550 surface2 = texturesurfacelist[j-1];
9551 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9552 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9553 GL_LockArrays(surface->num_firstvertex, numvertices);
9554 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9559 for (i = 0;i < texturenumsurfaces;i++)
9561 surface = texturesurfacelist[i];
9562 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9563 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);
9568 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9570 switch(vid.renderpath)
9572 case RENDERPATH_CGGL:
9574 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9575 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9578 case RENDERPATH_GL20:
9579 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9580 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9582 case RENDERPATH_GL13:
9583 case RENDERPATH_GL11:
9584 R_Mesh_TexBind(0, surface->lightmaptexture);
9589 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9591 // pick the closest matching water plane and bind textures
9592 int planeindex, vertexindex;
9596 r_waterstate_waterplane_t *p, *bestp;
9599 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9602 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9604 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9605 d += fabs(PlaneDiff(vert, &p->plane));
9607 if (bestd > d || !bestp)
9613 switch(vid.renderpath)
9615 case RENDERPATH_CGGL:
9617 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9618 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9621 case RENDERPATH_GL20:
9622 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9623 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9625 case RENDERPATH_GL13:
9626 case RENDERPATH_GL11:
9631 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9634 const msurface_t *surface;
9635 if (r_waterstate.renderingscene)
9637 for (i = 0;i < texturenumsurfaces;i++)
9639 surface = texturesurfacelist[i];
9640 RSurf_BindLightmapForSurface(surface);
9641 RSurf_BindReflectionForSurface(surface);
9642 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9643 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);
9647 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9651 const msurface_t *surface = texturesurfacelist[0];
9652 const msurface_t *surface2;
9657 if (texturenumsurfaces == 1)
9659 RSurf_BindLightmapForSurface(surface);
9660 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9661 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);
9663 else if (r_batchmode.integer == 2)
9665 #define MAXBATCHTRIANGLES 4096
9666 int batchtriangles = 0;
9667 static int batchelements[MAXBATCHTRIANGLES*3];
9668 for (i = 0;i < texturenumsurfaces;i = j)
9670 surface = texturesurfacelist[i];
9671 RSurf_BindLightmapForSurface(surface);
9673 if (surface->num_triangles > MAXBATCHTRIANGLES)
9675 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);
9678 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9679 batchtriangles = surface->num_triangles;
9680 firstvertex = surface->num_firstvertex;
9681 endvertex = surface->num_firstvertex + surface->num_vertices;
9682 for (;j < texturenumsurfaces;j++)
9684 surface2 = texturesurfacelist[j];
9685 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9687 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9688 batchtriangles += surface2->num_triangles;
9689 firstvertex = min(firstvertex, surface2->num_firstvertex);
9690 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9692 surface2 = texturesurfacelist[j-1];
9693 numvertices = endvertex - firstvertex;
9694 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9697 else if (r_batchmode.integer == 1)
9700 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9701 for (i = 0;i < texturenumsurfaces;i = j)
9703 surface = texturesurfacelist[i];
9704 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9705 if (texturesurfacelist[j] != surface2)
9707 Con_Printf(" %i", j - i);
9710 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9712 for (i = 0;i < texturenumsurfaces;i = j)
9714 surface = texturesurfacelist[i];
9715 RSurf_BindLightmapForSurface(surface);
9716 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9717 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9720 Con_Printf(" %i", j - i);
9722 surface2 = texturesurfacelist[j-1];
9723 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9724 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9725 GL_LockArrays(surface->num_firstvertex, numvertices);
9726 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9734 for (i = 0;i < texturenumsurfaces;i++)
9736 surface = texturesurfacelist[i];
9737 RSurf_BindLightmapForSurface(surface);
9738 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9739 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);
9744 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9747 int texturesurfaceindex;
9748 if (r_showsurfaces.integer == 2)
9750 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9752 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9753 for (j = 0;j < surface->num_triangles;j++)
9755 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9756 GL_Color(f, f, f, 1);
9757 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9763 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9765 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9766 int k = (int)(((size_t)surface) / sizeof(msurface_t));
9767 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);
9768 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9769 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);
9774 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9776 int texturesurfaceindex;
9780 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9782 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9783 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)
9791 rsurface.lightmapcolor4f = rsurface.array_color4f;
9792 rsurface.lightmapcolor4f_bufferobject = 0;
9793 rsurface.lightmapcolor4f_bufferoffset = 0;
9796 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9798 int texturesurfaceindex;
9804 if (rsurface.lightmapcolor4f)
9806 // generate color arrays for the surfaces in this list
9807 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9809 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9810 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)
9812 f = RSurf_FogVertex(v);
9822 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9824 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9825 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)
9827 f = RSurf_FogVertex(v);
9835 rsurface.lightmapcolor4f = rsurface.array_color4f;
9836 rsurface.lightmapcolor4f_bufferobject = 0;
9837 rsurface.lightmapcolor4f_bufferoffset = 0;
9840 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9842 int texturesurfaceindex;
9848 if (!rsurface.lightmapcolor4f)
9850 // generate color arrays for the surfaces in this list
9851 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9853 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9854 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)
9856 f = RSurf_FogVertex(v);
9857 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9858 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9859 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9863 rsurface.lightmapcolor4f = rsurface.array_color4f;
9864 rsurface.lightmapcolor4f_bufferobject = 0;
9865 rsurface.lightmapcolor4f_bufferoffset = 0;
9868 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
9870 int texturesurfaceindex;
9874 if (!rsurface.lightmapcolor4f)
9876 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9878 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9879 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)
9887 rsurface.lightmapcolor4f = rsurface.array_color4f;
9888 rsurface.lightmapcolor4f_bufferobject = 0;
9889 rsurface.lightmapcolor4f_bufferoffset = 0;
9892 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9894 int texturesurfaceindex;
9898 if (!rsurface.lightmapcolor4f)
9900 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9902 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9903 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)
9905 c2[0] = c[0] + r_refdef.scene.ambient;
9906 c2[1] = c[1] + r_refdef.scene.ambient;
9907 c2[2] = c[2] + r_refdef.scene.ambient;
9911 rsurface.lightmapcolor4f = rsurface.array_color4f;
9912 rsurface.lightmapcolor4f_bufferobject = 0;
9913 rsurface.lightmapcolor4f_bufferoffset = 0;
9916 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9919 rsurface.lightmapcolor4f = NULL;
9920 rsurface.lightmapcolor4f_bufferobject = 0;
9921 rsurface.lightmapcolor4f_bufferoffset = 0;
9922 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9923 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9924 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9925 GL_Color(r, g, b, a);
9926 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
9929 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9931 // TODO: optimize applyfog && applycolor case
9932 // just apply fog if necessary, and tint the fog color array if necessary
9933 rsurface.lightmapcolor4f = NULL;
9934 rsurface.lightmapcolor4f_bufferobject = 0;
9935 rsurface.lightmapcolor4f_bufferoffset = 0;
9936 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9937 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9938 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9939 GL_Color(r, g, b, a);
9940 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9943 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9945 int texturesurfaceindex;
9949 if (texturesurfacelist[0]->lightmapinfo)
9951 // generate color arrays for the surfaces in this list
9952 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9954 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9955 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
9957 if (surface->lightmapinfo->samples)
9959 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
9960 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
9961 VectorScale(lm, scale, c);
9962 if (surface->lightmapinfo->styles[1] != 255)
9964 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9966 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
9967 VectorMA(c, scale, lm, c);
9968 if (surface->lightmapinfo->styles[2] != 255)
9971 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
9972 VectorMA(c, scale, lm, c);
9973 if (surface->lightmapinfo->styles[3] != 255)
9976 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
9977 VectorMA(c, scale, lm, c);
9987 rsurface.lightmapcolor4f = rsurface.array_color4f;
9988 rsurface.lightmapcolor4f_bufferobject = 0;
9989 rsurface.lightmapcolor4f_bufferoffset = 0;
9993 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
9994 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
9995 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9997 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9998 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9999 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10000 GL_Color(r, g, b, a);
10001 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10004 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10006 int texturesurfaceindex;
10013 vec3_t ambientcolor;
10014 vec3_t diffusecolor;
10018 VectorCopy(rsurface.modellight_lightdir, lightdir);
10019 f = 0.5f * r_refdef.lightmapintensity;
10020 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10021 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10022 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10023 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10024 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10025 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10027 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10029 // generate color arrays for the surfaces in this list
10030 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10032 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10033 int numverts = surface->num_vertices;
10034 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10035 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10036 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10037 // q3-style directional shading
10038 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10040 if ((f = DotProduct(n, lightdir)) > 0)
10041 VectorMA(ambientcolor, f, diffusecolor, c);
10043 VectorCopy(ambientcolor, c);
10051 rsurface.lightmapcolor4f = rsurface.array_color4f;
10052 rsurface.lightmapcolor4f_bufferobject = 0;
10053 rsurface.lightmapcolor4f_bufferoffset = 0;
10054 *applycolor = false;
10058 *r = ambientcolor[0];
10059 *g = ambientcolor[1];
10060 *b = ambientcolor[2];
10061 rsurface.lightmapcolor4f = NULL;
10062 rsurface.lightmapcolor4f_bufferobject = 0;
10063 rsurface.lightmapcolor4f_bufferoffset = 0;
10067 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10069 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10070 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10071 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10072 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10073 GL_Color(r, g, b, a);
10074 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10077 void RSurf_SetupDepthAndCulling(void)
10079 // submodels are biased to avoid z-fighting with world surfaces that they
10080 // may be exactly overlapping (avoids z-fighting artifacts on certain
10081 // doors and things in Quake maps)
10082 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10083 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10084 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10085 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10088 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10090 // transparent sky would be ridiculous
10091 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10093 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10094 skyrenderlater = true;
10095 RSurf_SetupDepthAndCulling();
10096 GL_DepthMask(true);
10097 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10098 // skymasking on them, and Quake3 never did sky masking (unlike
10099 // software Quake and software Quake2), so disable the sky masking
10100 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10101 // and skymasking also looks very bad when noclipping outside the
10102 // level, so don't use it then either.
10103 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10105 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10106 R_Mesh_ColorPointer(NULL, 0, 0);
10107 R_Mesh_ResetTextureState();
10108 if (skyrendermasked)
10110 R_SetupShader_DepthOrShadow();
10111 // depth-only (masking)
10112 GL_ColorMask(0,0,0,0);
10113 // just to make sure that braindead drivers don't draw
10114 // anything despite that colormask...
10115 GL_BlendFunc(GL_ZERO, GL_ONE);
10119 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10121 GL_BlendFunc(GL_ONE, GL_ZERO);
10123 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10124 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10125 if (skyrendermasked)
10126 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10128 R_Mesh_ResetTextureState();
10129 GL_Color(1, 1, 1, 1);
10132 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10133 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10134 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10136 qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
10137 qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
10139 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10142 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10143 R_Mesh_ColorPointer(NULL, 0, 0);
10145 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10149 // render background
10150 GL_BlendFunc(GL_ONE, GL_ZERO);
10151 GL_DepthMask(true);
10152 GL_AlphaTest(false);
10154 GL_Color(1, 1, 1, 1);
10155 R_Mesh_ColorPointer(NULL, 0, 0);
10157 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10158 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10159 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10160 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10161 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10162 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10163 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10164 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10165 GL_LockArrays(0, 0);
10167 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10168 GL_DepthMask(false);
10169 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10170 R_Mesh_ColorPointer(NULL, 0, 0);
10172 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10175 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10177 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10178 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10179 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10180 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10181 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10183 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10186 GL_DepthMask(true);
10188 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10189 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10190 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
10192 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10194 if (refract || reflect)
10195 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10197 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10201 if (refract || reflect)
10202 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10204 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10206 GL_LockArrays(0, 0);
10209 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10211 // OpenGL 1.3 path - anything not completely ancient
10212 int texturesurfaceindex;
10213 qboolean applycolor;
10216 const texturelayer_t *layer;
10217 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10219 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10222 int layertexrgbscale;
10223 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10225 if (layerindex == 0)
10226 GL_AlphaTest(true);
10229 GL_AlphaTest(false);
10230 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10233 GL_DepthMask(layer->depthmask && writedepth);
10234 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10235 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10237 layertexrgbscale = 4;
10238 VectorScale(layer->color, 0.25f, layercolor);
10240 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10242 layertexrgbscale = 2;
10243 VectorScale(layer->color, 0.5f, layercolor);
10247 layertexrgbscale = 1;
10248 VectorScale(layer->color, 1.0f, layercolor);
10250 layercolor[3] = layer->color[3];
10251 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10252 R_Mesh_ColorPointer(NULL, 0, 0);
10253 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10254 switch (layer->type)
10256 case TEXTURELAYERTYPE_LITTEXTURE:
10257 // single-pass lightmapped texture with 2x rgbscale
10258 //R_Mesh_TexBind(0, r_texture_white);
10259 R_Mesh_TexMatrix(0, NULL);
10260 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10261 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10262 R_Mesh_TexBind(1, layer->texture);
10263 R_Mesh_TexMatrix(1, &layer->texmatrix);
10264 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10265 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10266 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10267 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10268 else if (rsurface.uselightmaptexture)
10269 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10271 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10273 case TEXTURELAYERTYPE_TEXTURE:
10274 // singletexture unlit texture with transparency support
10275 R_Mesh_TexBind(0, layer->texture);
10276 R_Mesh_TexMatrix(0, &layer->texmatrix);
10277 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10278 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10279 R_Mesh_TexBind(1, 0);
10280 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10281 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10283 case TEXTURELAYERTYPE_FOG:
10284 // singletexture fogging
10285 if (layer->texture)
10287 R_Mesh_TexBind(0, layer->texture);
10288 R_Mesh_TexMatrix(0, &layer->texmatrix);
10289 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10290 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10294 R_Mesh_TexBind(0, 0);
10295 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10297 R_Mesh_TexBind(1, 0);
10298 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10299 // generate a color array for the fog pass
10300 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10301 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10307 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10308 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)
10310 f = 1 - RSurf_FogVertex(v);
10311 c[0] = layercolor[0];
10312 c[1] = layercolor[1];
10313 c[2] = layercolor[2];
10314 c[3] = f * layercolor[3];
10317 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10320 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10322 GL_LockArrays(0, 0);
10325 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10327 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10328 GL_AlphaTest(false);
10332 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10334 // OpenGL 1.1 - crusty old voodoo path
10335 int texturesurfaceindex;
10338 const texturelayer_t *layer;
10339 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10341 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10343 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10345 if (layerindex == 0)
10346 GL_AlphaTest(true);
10349 GL_AlphaTest(false);
10350 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10353 GL_DepthMask(layer->depthmask && writedepth);
10354 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10355 R_Mesh_ColorPointer(NULL, 0, 0);
10356 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10357 switch (layer->type)
10359 case TEXTURELAYERTYPE_LITTEXTURE:
10360 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10362 // two-pass lit texture with 2x rgbscale
10363 // first the lightmap pass
10364 //R_Mesh_TexBind(0, r_texture_white);
10365 R_Mesh_TexMatrix(0, NULL);
10366 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10367 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10368 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10369 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10370 else if (rsurface.uselightmaptexture)
10371 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10373 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10374 GL_LockArrays(0, 0);
10375 // then apply the texture to it
10376 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10377 R_Mesh_TexBind(0, layer->texture);
10378 R_Mesh_TexMatrix(0, &layer->texmatrix);
10379 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10380 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10381 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);
10385 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10386 R_Mesh_TexBind(0, layer->texture);
10387 R_Mesh_TexMatrix(0, &layer->texmatrix);
10388 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10389 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10390 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10391 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);
10393 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);
10396 case TEXTURELAYERTYPE_TEXTURE:
10397 // singletexture unlit texture with transparency support
10398 R_Mesh_TexBind(0, layer->texture);
10399 R_Mesh_TexMatrix(0, &layer->texmatrix);
10400 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10401 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10402 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);
10404 case TEXTURELAYERTYPE_FOG:
10405 // singletexture fogging
10406 if (layer->texture)
10408 R_Mesh_TexBind(0, layer->texture);
10409 R_Mesh_TexMatrix(0, &layer->texmatrix);
10410 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10411 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10415 R_Mesh_TexBind(0, 0);
10416 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10418 // generate a color array for the fog pass
10419 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10420 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10426 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10427 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)
10429 f = 1 - RSurf_FogVertex(v);
10430 c[0] = layer->color[0];
10431 c[1] = layer->color[1];
10432 c[2] = layer->color[2];
10433 c[3] = f * layer->color[3];
10436 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10439 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10441 GL_LockArrays(0, 0);
10444 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10446 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10447 GL_AlphaTest(false);
10451 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10455 GL_AlphaTest(false);
10456 R_Mesh_ColorPointer(NULL, 0, 0);
10457 R_Mesh_ResetTextureState();
10458 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10460 if(rsurface.texture && rsurface.texture->currentskinframe)
10462 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10463 c[3] *= rsurface.texture->currentalpha;
10473 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10475 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10476 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10477 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10480 // brighten it up (as texture value 127 means "unlit")
10481 c[0] *= 2 * r_refdef.view.colorscale;
10482 c[1] *= 2 * r_refdef.view.colorscale;
10483 c[2] *= 2 * r_refdef.view.colorscale;
10485 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10486 c[3] *= r_wateralpha.value;
10488 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10490 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10491 GL_DepthMask(false);
10493 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10495 GL_BlendFunc(GL_ONE, GL_ONE);
10496 GL_DepthMask(false);
10498 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10500 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10501 GL_DepthMask(false);
10503 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10505 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10506 GL_DepthMask(false);
10510 GL_BlendFunc(GL_ONE, GL_ZERO);
10511 GL_DepthMask(writedepth);
10514 rsurface.lightmapcolor4f = NULL;
10516 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10518 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10520 rsurface.lightmapcolor4f = NULL;
10521 rsurface.lightmapcolor4f_bufferobject = 0;
10522 rsurface.lightmapcolor4f_bufferoffset = 0;
10524 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10526 qboolean applycolor = true;
10529 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10531 r_refdef.lightmapintensity = 1;
10532 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10533 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10537 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10539 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10540 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10541 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10544 if(!rsurface.lightmapcolor4f)
10545 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10547 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10548 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10549 if(r_refdef.fogenabled)
10550 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10552 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10553 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10556 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10559 RSurf_SetupDepthAndCulling();
10560 if (r_showsurfaces.integer == 3 && !prepass)
10562 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10565 switch (vid.renderpath)
10567 case RENDERPATH_GL20:
10568 case RENDERPATH_CGGL:
10569 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10571 case RENDERPATH_GL13:
10572 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10574 case RENDERPATH_GL11:
10575 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10581 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10584 RSurf_SetupDepthAndCulling();
10585 if (r_showsurfaces.integer == 3 && !prepass)
10587 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10590 switch (vid.renderpath)
10592 case RENDERPATH_GL20:
10593 case RENDERPATH_CGGL:
10594 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10596 case RENDERPATH_GL13:
10597 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10599 case RENDERPATH_GL11:
10600 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10606 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10609 int texturenumsurfaces, endsurface;
10610 texture_t *texture;
10611 const msurface_t *surface;
10612 const msurface_t *texturesurfacelist[256];
10614 // if the model is static it doesn't matter what value we give for
10615 // wantnormals and wanttangents, so this logic uses only rules applicable
10616 // to a model, knowing that they are meaningless otherwise
10617 if (ent == r_refdef.scene.worldentity)
10618 RSurf_ActiveWorldEntity();
10619 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10620 RSurf_ActiveModelEntity(ent, false, false, false);
10623 switch (vid.renderpath)
10625 case RENDERPATH_GL20:
10626 case RENDERPATH_CGGL:
10627 RSurf_ActiveModelEntity(ent, true, true, false);
10629 case RENDERPATH_GL13:
10630 case RENDERPATH_GL11:
10631 RSurf_ActiveModelEntity(ent, true, false, false);
10636 if (r_transparentdepthmasking.integer)
10638 qboolean setup = false;
10639 for (i = 0;i < numsurfaces;i = j)
10642 surface = rsurface.modelsurfaces + surfacelist[i];
10643 texture = surface->texture;
10644 rsurface.texture = R_GetCurrentTexture(texture);
10645 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10646 // scan ahead until we find a different texture
10647 endsurface = min(i + 1024, numsurfaces);
10648 texturenumsurfaces = 0;
10649 texturesurfacelist[texturenumsurfaces++] = surface;
10650 for (;j < endsurface;j++)
10652 surface = rsurface.modelsurfaces + surfacelist[j];
10653 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10655 texturesurfacelist[texturenumsurfaces++] = surface;
10657 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10659 // render the range of surfaces as depth
10663 GL_ColorMask(0,0,0,0);
10665 GL_DepthTest(true);
10666 GL_BlendFunc(GL_ONE, GL_ZERO);
10667 GL_DepthMask(true);
10668 GL_AlphaTest(false);
10669 R_Mesh_ColorPointer(NULL, 0, 0);
10670 R_Mesh_ResetTextureState();
10671 R_SetupShader_DepthOrShadow();
10673 RSurf_SetupDepthAndCulling();
10674 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10675 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10678 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10681 for (i = 0;i < numsurfaces;i = j)
10684 surface = rsurface.modelsurfaces + surfacelist[i];
10685 texture = surface->texture;
10686 rsurface.texture = R_GetCurrentTexture(texture);
10687 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10688 // scan ahead until we find a different texture
10689 endsurface = min(i + 1024, numsurfaces);
10690 texturenumsurfaces = 0;
10691 texturesurfacelist[texturenumsurfaces++] = surface;
10692 for (;j < endsurface;j++)
10694 surface = rsurface.modelsurfaces + surfacelist[j];
10695 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10697 texturesurfacelist[texturenumsurfaces++] = surface;
10699 // render the range of surfaces
10700 if (ent == r_refdef.scene.worldentity)
10701 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10703 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10705 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10706 GL_AlphaTest(false);
10709 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10711 // transparent surfaces get pushed off into the transparent queue
10712 int surfacelistindex;
10713 const msurface_t *surface;
10714 vec3_t tempcenter, center;
10715 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10717 surface = texturesurfacelist[surfacelistindex];
10718 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10719 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10720 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10721 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10722 if (queueentity->transparent_offset) // transparent offset
10724 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10725 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10726 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10728 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10732 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10734 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10738 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10740 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10742 RSurf_SetupDepthAndCulling();
10743 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10744 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10748 if (!rsurface.texture->currentnumlayers)
10750 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10751 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10753 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10755 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10757 RSurf_SetupDepthAndCulling();
10758 GL_AlphaTest(false);
10759 R_Mesh_ColorPointer(NULL, 0, 0);
10760 R_Mesh_ResetTextureState();
10761 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10762 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10763 GL_DepthMask(true);
10764 GL_BlendFunc(GL_ONE, GL_ZERO);
10765 GL_Color(0, 0, 0, 1);
10766 GL_DepthTest(writedepth);
10767 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10769 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10771 RSurf_SetupDepthAndCulling();
10772 GL_AlphaTest(false);
10773 R_Mesh_ColorPointer(NULL, 0, 0);
10774 R_Mesh_ResetTextureState();
10775 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10776 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10777 GL_DepthMask(true);
10778 GL_BlendFunc(GL_ONE, GL_ZERO);
10779 GL_DepthTest(true);
10780 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10782 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10783 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10784 else if (!rsurface.texture->currentnumlayers)
10786 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10788 // in the deferred case, transparent surfaces were queued during prepass
10789 if (!r_shadow_usingdeferredprepass)
10790 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10794 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10795 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10800 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10803 texture_t *texture;
10804 // break the surface list down into batches by texture and use of lightmapping
10805 for (i = 0;i < numsurfaces;i = j)
10808 // texture is the base texture pointer, rsurface.texture is the
10809 // current frame/skin the texture is directing us to use (for example
10810 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10811 // use skin 1 instead)
10812 texture = surfacelist[i]->texture;
10813 rsurface.texture = R_GetCurrentTexture(texture);
10814 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10815 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10817 // if this texture is not the kind we want, skip ahead to the next one
10818 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10822 // simply scan ahead until we find a different texture or lightmap state
10823 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10825 // render the range of surfaces
10826 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10830 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10835 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10837 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10839 RSurf_SetupDepthAndCulling();
10840 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10841 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10845 if (!rsurface.texture->currentnumlayers)
10847 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10848 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10850 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10852 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10854 RSurf_SetupDepthAndCulling();
10855 GL_AlphaTest(false);
10856 R_Mesh_ColorPointer(NULL, 0, 0);
10857 R_Mesh_ResetTextureState();
10858 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10859 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10860 GL_DepthMask(true);
10861 GL_BlendFunc(GL_ONE, GL_ZERO);
10862 GL_Color(0, 0, 0, 1);
10863 GL_DepthTest(writedepth);
10864 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10866 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10868 RSurf_SetupDepthAndCulling();
10869 GL_AlphaTest(false);
10870 R_Mesh_ColorPointer(NULL, 0, 0);
10871 R_Mesh_ResetTextureState();
10872 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10873 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10874 GL_DepthMask(true);
10875 GL_BlendFunc(GL_ONE, GL_ZERO);
10876 GL_DepthTest(true);
10877 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10879 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10880 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10881 else if (!rsurface.texture->currentnumlayers)
10883 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10885 // in the deferred case, transparent surfaces were queued during prepass
10886 if (!r_shadow_usingdeferredprepass)
10887 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10891 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10892 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10897 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10900 texture_t *texture;
10901 // break the surface list down into batches by texture and use of lightmapping
10902 for (i = 0;i < numsurfaces;i = j)
10905 // texture is the base texture pointer, rsurface.texture is the
10906 // current frame/skin the texture is directing us to use (for example
10907 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10908 // use skin 1 instead)
10909 texture = surfacelist[i]->texture;
10910 rsurface.texture = R_GetCurrentTexture(texture);
10911 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10912 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10914 // if this texture is not the kind we want, skip ahead to the next one
10915 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10919 // simply scan ahead until we find a different texture or lightmap state
10920 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10922 // render the range of surfaces
10923 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10927 float locboxvertex3f[6*4*3] =
10929 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10930 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10931 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10932 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10933 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10934 1,0,0, 0,0,0, 0,1,0, 1,1,0
10937 unsigned short locboxelements[6*2*3] =
10942 12,13,14, 12,14,15,
10943 16,17,18, 16,18,19,
10947 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10950 cl_locnode_t *loc = (cl_locnode_t *)ent;
10952 float vertex3f[6*4*3];
10954 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10955 GL_DepthMask(false);
10956 GL_DepthRange(0, 1);
10957 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10958 GL_DepthTest(true);
10959 GL_CullFace(GL_NONE);
10960 R_EntityMatrix(&identitymatrix);
10962 R_Mesh_VertexPointer(vertex3f, 0, 0);
10963 R_Mesh_ColorPointer(NULL, 0, 0);
10964 R_Mesh_ResetTextureState();
10965 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10967 i = surfacelist[0];
10968 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10969 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10970 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10971 surfacelist[0] < 0 ? 0.5f : 0.125f);
10973 if (VectorCompare(loc->mins, loc->maxs))
10975 VectorSet(size, 2, 2, 2);
10976 VectorMA(loc->mins, -0.5f, size, mins);
10980 VectorCopy(loc->mins, mins);
10981 VectorSubtract(loc->maxs, loc->mins, size);
10984 for (i = 0;i < 6*4*3;)
10985 for (j = 0;j < 3;j++, i++)
10986 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10988 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
10991 void R_DrawLocs(void)
10994 cl_locnode_t *loc, *nearestloc;
10996 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10997 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10999 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11000 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11004 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11006 if (decalsystem->decals)
11007 Mem_Free(decalsystem->decals);
11008 memset(decalsystem, 0, sizeof(*decalsystem));
11011 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)
11014 tridecal_t *decals;
11018 // expand or initialize the system
11019 if (decalsystem->maxdecals <= decalsystem->numdecals)
11021 decalsystem_t old = *decalsystem;
11022 qboolean useshortelements;
11023 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11024 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11025 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)));
11026 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11027 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11028 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11029 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11030 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11031 if (decalsystem->numdecals)
11032 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11034 Mem_Free(old.decals);
11035 for (i = 0;i < decalsystem->maxdecals*3;i++)
11036 decalsystem->element3i[i] = i;
11037 if (useshortelements)
11038 for (i = 0;i < decalsystem->maxdecals*3;i++)
11039 decalsystem->element3s[i] = i;
11042 // grab a decal and search for another free slot for the next one
11043 maxdecals = decalsystem->maxdecals;
11044 decals = decalsystem->decals;
11045 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11046 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11048 decalsystem->freedecal = i;
11049 if (decalsystem->numdecals <= i)
11050 decalsystem->numdecals = i + 1;
11052 // initialize the decal
11054 decal->triangleindex = triangleindex;
11055 decal->surfaceindex = surfaceindex;
11056 decal->decalsequence = decalsequence;
11057 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11058 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11059 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11060 decal->color4ub[0][3] = 255;
11061 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11062 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11063 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11064 decal->color4ub[1][3] = 255;
11065 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11066 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11067 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11068 decal->color4ub[2][3] = 255;
11069 decal->vertex3f[0][0] = v0[0];
11070 decal->vertex3f[0][1] = v0[1];
11071 decal->vertex3f[0][2] = v0[2];
11072 decal->vertex3f[1][0] = v1[0];
11073 decal->vertex3f[1][1] = v1[1];
11074 decal->vertex3f[1][2] = v1[2];
11075 decal->vertex3f[2][0] = v2[0];
11076 decal->vertex3f[2][1] = v2[1];
11077 decal->vertex3f[2][2] = v2[2];
11078 decal->texcoord2f[0][0] = t0[0];
11079 decal->texcoord2f[0][1] = t0[1];
11080 decal->texcoord2f[1][0] = t1[0];
11081 decal->texcoord2f[1][1] = t1[1];
11082 decal->texcoord2f[2][0] = t2[0];
11083 decal->texcoord2f[2][1] = t2[1];
11086 extern cvar_t cl_decals_bias;
11087 extern cvar_t cl_decals_models;
11088 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11089 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)
11091 matrix4x4_t projection;
11092 decalsystem_t *decalsystem;
11095 const float *vertex3f;
11096 const msurface_t *surface;
11097 const msurface_t *surfaces;
11098 const int *surfacelist;
11099 const texture_t *texture;
11102 int numsurfacelist;
11103 int surfacelistindex;
11106 int decalsurfaceindex;
11111 float localorigin[3];
11112 float localnormal[3];
11113 float localmins[3];
11114 float localmaxs[3];
11121 float planes[6][4];
11123 float points[2][9][3];
11127 decalsystem = &ent->decalsystem;
11128 model = ent->model;
11129 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11131 R_DecalSystem_Reset(&ent->decalsystem);
11135 if (!model->brush.data_nodes && !cl_decals_models.integer)
11137 if (decalsystem->model)
11138 R_DecalSystem_Reset(decalsystem);
11142 if (decalsystem->model != model)
11143 R_DecalSystem_Reset(decalsystem);
11144 decalsystem->model = model;
11146 RSurf_ActiveModelEntity(ent, false, false, false);
11148 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11149 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11150 VectorNormalize(localnormal);
11151 localsize = worldsize*rsurface.inversematrixscale;
11152 ilocalsize = 1.0f / localsize;
11153 localmins[0] = localorigin[0] - localsize;
11154 localmins[1] = localorigin[1] - localsize;
11155 localmins[2] = localorigin[2] - localsize;
11156 localmaxs[0] = localorigin[0] + localsize;
11157 localmaxs[1] = localorigin[1] + localsize;
11158 localmaxs[2] = localorigin[2] + localsize;
11160 //VectorCopy(localnormal, planes[4]);
11161 //VectorVectors(planes[4], planes[2], planes[0]);
11162 AnglesFromVectors(angles, localnormal, NULL, false);
11163 AngleVectors(angles, planes[0], planes[2], planes[4]);
11164 VectorNegate(planes[0], planes[1]);
11165 VectorNegate(planes[2], planes[3]);
11166 VectorNegate(planes[4], planes[5]);
11167 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11168 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11169 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11170 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11171 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11172 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11177 matrix4x4_t forwardprojection;
11178 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11179 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11184 float projectionvector[4][3];
11185 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11186 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11187 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11188 projectionvector[0][0] = planes[0][0] * ilocalsize;
11189 projectionvector[0][1] = planes[1][0] * ilocalsize;
11190 projectionvector[0][2] = planes[2][0] * ilocalsize;
11191 projectionvector[1][0] = planes[0][1] * ilocalsize;
11192 projectionvector[1][1] = planes[1][1] * ilocalsize;
11193 projectionvector[1][2] = planes[2][1] * ilocalsize;
11194 projectionvector[2][0] = planes[0][2] * ilocalsize;
11195 projectionvector[2][1] = planes[1][2] * ilocalsize;
11196 projectionvector[2][2] = planes[2][2] * ilocalsize;
11197 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11198 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11199 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11200 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11204 dynamic = model->surfmesh.isanimated;
11205 vertex3f = rsurface.modelvertex3f;
11206 numsurfacelist = model->nummodelsurfaces;
11207 surfacelist = model->sortedmodelsurfaces;
11208 surfaces = model->data_surfaces;
11209 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11211 surfaceindex = surfacelist[surfacelistindex];
11212 surface = surfaces + surfaceindex;
11213 // skip transparent surfaces
11214 texture = surface->texture;
11215 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11217 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11219 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11221 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11222 numvertices = surface->num_vertices;
11223 numtriangles = surface->num_triangles;
11224 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11226 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11228 index = 3*e[cornerindex];
11229 VectorCopy(vertex3f + index, v[cornerindex]);
11232 //TriangleNormal(v[0], v[1], v[2], normal);
11233 //if (DotProduct(normal, localnormal) < 0.0f)
11235 // clip by each of the box planes formed from the projection matrix
11236 // if anything survives, we emit the decal
11237 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]);
11240 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]);
11243 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]);
11246 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]);
11249 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]);
11252 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]);
11255 // some part of the triangle survived, so we have to accept it...
11258 // dynamic always uses the original triangle
11260 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11262 index = 3*e[cornerindex];
11263 VectorCopy(vertex3f + index, v[cornerindex]);
11266 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11268 // convert vertex positions to texcoords
11269 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11270 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11271 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11272 // calculate distance fade from the projection origin
11273 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11274 f = bound(0.0f, f, 1.0f);
11275 c[cornerindex][0] = r * f;
11276 c[cornerindex][1] = g * f;
11277 c[cornerindex][2] = b * f;
11278 c[cornerindex][3] = 1.0f;
11279 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11282 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);
11284 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11285 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);
11290 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11291 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)
11293 int renderentityindex;
11294 float worldmins[3];
11295 float worldmaxs[3];
11296 entity_render_t *ent;
11298 if (!cl_decals_newsystem.integer)
11301 worldmins[0] = worldorigin[0] - worldsize;
11302 worldmins[1] = worldorigin[1] - worldsize;
11303 worldmins[2] = worldorigin[2] - worldsize;
11304 worldmaxs[0] = worldorigin[0] + worldsize;
11305 worldmaxs[1] = worldorigin[1] + worldsize;
11306 worldmaxs[2] = worldorigin[2] + worldsize;
11308 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11310 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11312 ent = r_refdef.scene.entities[renderentityindex];
11313 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11316 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11320 typedef struct r_decalsystem_splatqueue_s
11322 vec3_t worldorigin;
11323 vec3_t worldnormal;
11329 r_decalsystem_splatqueue_t;
11331 int r_decalsystem_numqueued = 0;
11332 #define MAX_DECALSYSTEM_QUEUE 1024
11333 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11335 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)
11337 r_decalsystem_splatqueue_t *queue;
11339 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11342 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11343 VectorCopy(worldorigin, queue->worldorigin);
11344 VectorCopy(worldnormal, queue->worldnormal);
11345 Vector4Set(queue->color, r, g, b, a);
11346 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11347 queue->worldsize = worldsize;
11348 queue->decalsequence = cl.decalsequence++;
11351 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11354 r_decalsystem_splatqueue_t *queue;
11356 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11357 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);
11358 r_decalsystem_numqueued = 0;
11361 extern cvar_t cl_decals_max;
11362 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11365 decalsystem_t *decalsystem = &ent->decalsystem;
11372 if (!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 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11385 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11387 if (decalsystem->lastupdatetime)
11388 frametime = (cl.time - decalsystem->lastupdatetime);
11391 decalsystem->lastupdatetime = cl.time;
11392 decal = decalsystem->decals;
11393 numdecals = decalsystem->numdecals;
11395 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11397 if (decal->color4ub[0][3])
11399 decal->lived += frametime;
11400 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11402 memset(decal, 0, sizeof(*decal));
11403 if (decalsystem->freedecal > i)
11404 decalsystem->freedecal = i;
11408 decal = decalsystem->decals;
11409 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11412 // collapse the array by shuffling the tail decals into the gaps
11415 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11416 decalsystem->freedecal++;
11417 if (decalsystem->freedecal == numdecals)
11419 decal[decalsystem->freedecal] = decal[--numdecals];
11422 decalsystem->numdecals = numdecals;
11424 if (numdecals <= 0)
11426 // if there are no decals left, reset decalsystem
11427 R_DecalSystem_Reset(decalsystem);
11431 extern skinframe_t *decalskinframe;
11432 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11435 decalsystem_t *decalsystem = &ent->decalsystem;
11445 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11448 numdecals = decalsystem->numdecals;
11452 if (r_showsurfaces.integer)
11455 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11457 R_DecalSystem_Reset(decalsystem);
11461 // if the model is static it doesn't matter what value we give for
11462 // wantnormals and wanttangents, so this logic uses only rules applicable
11463 // to a model, knowing that they are meaningless otherwise
11464 if (ent == r_refdef.scene.worldentity)
11465 RSurf_ActiveWorldEntity();
11467 RSurf_ActiveModelEntity(ent, false, false, false);
11469 decalsystem->lastupdatetime = cl.time;
11470 decal = decalsystem->decals;
11472 fadedelay = cl_decals_time.value;
11473 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11475 // update vertex positions for animated models
11476 v3f = decalsystem->vertex3f;
11477 c4f = decalsystem->color4f;
11478 t2f = decalsystem->texcoord2f;
11479 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11481 if (!decal->color4ub[0][3])
11484 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11487 // update color values for fading decals
11488 if (decal->lived >= cl_decals_time.value)
11490 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11491 alpha *= (1.0f/255.0f);
11494 alpha = 1.0f/255.0f;
11496 c4f[ 0] = decal->color4ub[0][0] * alpha;
11497 c4f[ 1] = decal->color4ub[0][1] * alpha;
11498 c4f[ 2] = decal->color4ub[0][2] * alpha;
11500 c4f[ 4] = decal->color4ub[1][0] * alpha;
11501 c4f[ 5] = decal->color4ub[1][1] * alpha;
11502 c4f[ 6] = decal->color4ub[1][2] * alpha;
11504 c4f[ 8] = decal->color4ub[2][0] * alpha;
11505 c4f[ 9] = decal->color4ub[2][1] * alpha;
11506 c4f[10] = decal->color4ub[2][2] * alpha;
11509 t2f[0] = decal->texcoord2f[0][0];
11510 t2f[1] = decal->texcoord2f[0][1];
11511 t2f[2] = decal->texcoord2f[1][0];
11512 t2f[3] = decal->texcoord2f[1][1];
11513 t2f[4] = decal->texcoord2f[2][0];
11514 t2f[5] = decal->texcoord2f[2][1];
11516 // update vertex positions for animated models
11517 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11519 e = rsurface.modelelement3i + 3*decal->triangleindex;
11520 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11521 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11522 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11526 VectorCopy(decal->vertex3f[0], v3f);
11527 VectorCopy(decal->vertex3f[1], v3f + 3);
11528 VectorCopy(decal->vertex3f[2], v3f + 6);
11539 r_refdef.stats.drawndecals += numtris;
11541 if (r_refdef.fogenabled)
11543 switch(vid.renderpath)
11545 case RENDERPATH_GL20:
11546 case RENDERPATH_CGGL:
11547 case RENDERPATH_GL13:
11548 case RENDERPATH_GL11:
11549 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11551 alpha = RSurf_FogVertex(v3f);
11560 // now render the decals all at once
11561 // (this assumes they all use one particle font texture!)
11562 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);
11563 R_Mesh_ResetTextureState();
11564 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11565 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11566 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11567 GL_DepthMask(false);
11568 GL_DepthRange(0, 1);
11569 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11570 GL_DepthTest(true);
11571 GL_CullFace(GL_NONE);
11572 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11573 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11574 GL_LockArrays(0, numtris * 3);
11575 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11576 GL_LockArrays(0, 0);
11580 static void R_DrawModelDecals(void)
11584 // fade faster when there are too many decals
11585 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11586 for (i = 0;i < r_refdef.scene.numentities;i++)
11587 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11589 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11590 for (i = 0;i < r_refdef.scene.numentities;i++)
11591 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11592 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11594 R_DecalSystem_ApplySplatEntitiesQueue();
11596 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11597 for (i = 0;i < r_refdef.scene.numentities;i++)
11598 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11600 r_refdef.stats.totaldecals += numdecals;
11602 if (r_showsurfaces.integer)
11605 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11607 for (i = 0;i < r_refdef.scene.numentities;i++)
11609 if (!r_refdef.viewcache.entityvisible[i])
11611 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11612 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11616 void R_DrawDebugModel(void)
11618 entity_render_t *ent = rsurface.entity;
11619 int i, j, k, l, flagsmask;
11620 const int *elements;
11622 const msurface_t *surface;
11623 dp_model_t *model = ent->model;
11626 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11628 R_Mesh_ColorPointer(NULL, 0, 0);
11629 R_Mesh_ResetTextureState();
11630 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11631 GL_DepthRange(0, 1);
11632 GL_DepthTest(!r_showdisabledepthtest.integer);
11633 GL_DepthMask(false);
11634 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11636 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11638 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11639 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11641 if (brush->colbrushf && brush->colbrushf->numtriangles)
11643 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11644 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);
11645 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11648 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11650 if (surface->num_collisiontriangles)
11652 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11653 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);
11654 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11659 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11661 if (r_showtris.integer || r_shownormals.integer)
11663 if (r_showdisabledepthtest.integer)
11665 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11666 GL_DepthMask(false);
11670 GL_BlendFunc(GL_ONE, GL_ZERO);
11671 GL_DepthMask(true);
11673 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11675 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11677 rsurface.texture = R_GetCurrentTexture(surface->texture);
11678 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11680 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11681 if (r_showtris.value > 0)
11683 if (!rsurface.texture->currentlayers->depthmask)
11684 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11685 else if (ent == r_refdef.scene.worldentity)
11686 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11688 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11689 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11690 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11691 R_Mesh_ColorPointer(NULL, 0, 0);
11692 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11693 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11694 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11695 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);
11696 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11699 if (r_shownormals.value < 0)
11701 qglBegin(GL_LINES);
11702 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11704 VectorCopy(rsurface.vertex3f + l * 3, v);
11705 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11706 qglVertex3f(v[0], v[1], v[2]);
11707 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11708 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11709 qglVertex3f(v[0], v[1], v[2]);
11714 if (r_shownormals.value > 0)
11716 qglBegin(GL_LINES);
11717 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11719 VectorCopy(rsurface.vertex3f + l * 3, v);
11720 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11721 qglVertex3f(v[0], v[1], v[2]);
11722 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11723 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11724 qglVertex3f(v[0], v[1], v[2]);
11728 qglBegin(GL_LINES);
11729 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11731 VectorCopy(rsurface.vertex3f + l * 3, v);
11732 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11733 qglVertex3f(v[0], v[1], v[2]);
11734 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11735 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11736 qglVertex3f(v[0], v[1], v[2]);
11740 qglBegin(GL_LINES);
11741 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11743 VectorCopy(rsurface.vertex3f + l * 3, v);
11744 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11745 qglVertex3f(v[0], v[1], v[2]);
11746 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11747 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11748 qglVertex3f(v[0], v[1], v[2]);
11755 rsurface.texture = NULL;
11759 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11760 int r_maxsurfacelist = 0;
11761 const msurface_t **r_surfacelist = NULL;
11762 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11764 int i, j, endj, f, flagsmask;
11766 dp_model_t *model = r_refdef.scene.worldmodel;
11767 msurface_t *surfaces;
11768 unsigned char *update;
11769 int numsurfacelist = 0;
11773 if (r_maxsurfacelist < model->num_surfaces)
11775 r_maxsurfacelist = model->num_surfaces;
11777 Mem_Free((msurface_t**)r_surfacelist);
11778 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11781 RSurf_ActiveWorldEntity();
11783 surfaces = model->data_surfaces;
11784 update = model->brushq1.lightmapupdateflags;
11786 // update light styles on this submodel
11787 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11789 model_brush_lightstyleinfo_t *style;
11790 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11792 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11794 int *list = style->surfacelist;
11795 style->value = r_refdef.scene.lightstylevalue[style->style];
11796 for (j = 0;j < style->numsurfaces;j++)
11797 update[list[j]] = true;
11802 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11806 R_DrawDebugModel();
11807 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11813 rsurface.uselightmaptexture = false;
11814 rsurface.texture = NULL;
11815 rsurface.rtlight = NULL;
11816 numsurfacelist = 0;
11817 // add visible surfaces to draw list
11818 for (i = 0;i < model->nummodelsurfaces;i++)
11820 j = model->sortedmodelsurfaces[i];
11821 if (r_refdef.viewcache.world_surfacevisible[j])
11822 r_surfacelist[numsurfacelist++] = surfaces + j;
11824 // update lightmaps if needed
11828 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11830 if (r_refdef.viewcache.world_surfacevisible[j])
11835 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11840 // don't do anything if there were no surfaces
11841 if (!numsurfacelist)
11843 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11846 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11847 GL_AlphaTest(false);
11849 // add to stats if desired
11850 if (r_speeds.integer && !skysurfaces && !depthonly)
11852 r_refdef.stats.world_surfaces += numsurfacelist;
11853 for (j = 0;j < numsurfacelist;j++)
11854 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11857 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11860 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11862 int i, j, endj, f, flagsmask;
11864 dp_model_t *model = ent->model;
11865 msurface_t *surfaces;
11866 unsigned char *update;
11867 int numsurfacelist = 0;
11871 if (r_maxsurfacelist < model->num_surfaces)
11873 r_maxsurfacelist = model->num_surfaces;
11875 Mem_Free((msurface_t **)r_surfacelist);
11876 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11879 // if the model is static it doesn't matter what value we give for
11880 // wantnormals and wanttangents, so this logic uses only rules applicable
11881 // to a model, knowing that they are meaningless otherwise
11882 if (ent == r_refdef.scene.worldentity)
11883 RSurf_ActiveWorldEntity();
11884 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11885 RSurf_ActiveModelEntity(ent, false, false, false);
11887 RSurf_ActiveModelEntity(ent, true, true, true);
11888 else if (depthonly)
11889 RSurf_ActiveModelEntity(ent, false, false, false);
11892 switch (vid.renderpath)
11894 case RENDERPATH_GL20:
11895 case RENDERPATH_CGGL:
11896 RSurf_ActiveModelEntity(ent, true, true, false);
11898 case RENDERPATH_GL13:
11899 case RENDERPATH_GL11:
11900 RSurf_ActiveModelEntity(ent, true, false, false);
11905 surfaces = model->data_surfaces;
11906 update = model->brushq1.lightmapupdateflags;
11908 // update light styles
11909 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11911 model_brush_lightstyleinfo_t *style;
11912 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11914 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11916 int *list = style->surfacelist;
11917 style->value = r_refdef.scene.lightstylevalue[style->style];
11918 for (j = 0;j < style->numsurfaces;j++)
11919 update[list[j]] = true;
11924 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11928 R_DrawDebugModel();
11929 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11935 rsurface.uselightmaptexture = false;
11936 rsurface.texture = NULL;
11937 rsurface.rtlight = NULL;
11938 numsurfacelist = 0;
11939 // add visible surfaces to draw list
11940 for (i = 0;i < model->nummodelsurfaces;i++)
11941 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11942 // don't do anything if there were no surfaces
11943 if (!numsurfacelist)
11945 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11948 // update lightmaps if needed
11952 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11957 R_BuildLightMap(ent, surfaces + j);
11962 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11964 R_BuildLightMap(ent, surfaces + j);
11965 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11966 GL_AlphaTest(false);
11968 // add to stats if desired
11969 if (r_speeds.integer && !skysurfaces && !depthonly)
11971 r_refdef.stats.entities_surfaces += numsurfacelist;
11972 for (j = 0;j < numsurfacelist;j++)
11973 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11976 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11979 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11981 static texture_t texture;
11982 static msurface_t surface;
11983 const msurface_t *surfacelist = &surface;
11985 // fake enough texture and surface state to render this geometry
11987 texture.update_lastrenderframe = -1; // regenerate this texture
11988 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11989 texture.currentskinframe = skinframe;
11990 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11991 texture.specularscalemod = 1;
11992 texture.specularpowermod = 1;
11994 surface.texture = &texture;
11995 surface.num_triangles = numtriangles;
11996 surface.num_firsttriangle = firsttriangle;
11997 surface.num_vertices = numvertices;
11998 surface.num_firstvertex = firstvertex;
12001 rsurface.texture = R_GetCurrentTexture(surface.texture);
12002 rsurface.uselightmaptexture = false;
12003 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12006 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)
12008 static msurface_t surface;
12009 const msurface_t *surfacelist = &surface;
12011 // fake enough texture and surface state to render this geometry
12013 surface.texture = texture;
12014 surface.num_triangles = numtriangles;
12015 surface.num_firsttriangle = firsttriangle;
12016 surface.num_vertices = numvertices;
12017 surface.num_firstvertex = firstvertex;
12020 rsurface.texture = R_GetCurrentTexture(surface.texture);
12021 rsurface.uselightmaptexture = false;
12022 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);