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", "0", "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) && defined(USEDIFFUSE)\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, ivec2(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].rgb *= cubecolor;\n"
1365 " gl_FragData[1].rgb *= 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 "#ifdef USEDIFFUSE\n"
1551 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1553 "#define lightcolor LightColor\n"
1554 "#endif // MODE_LIGHTDIRECTION\n"
1555 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1557 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1558 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1559 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1560 " // convert modelspace light vector to tangentspace\n"
1561 " myhalf3 lightnormal;\n"
1562 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1563 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1564 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1565 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1566 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1567 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1568 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1569 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1570 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1571 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1572 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1573 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1574 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1575 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1576 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1578 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1579 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1580 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1586 "#ifdef MODE_LIGHTMAP\n"
1587 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1588 "#endif // MODE_LIGHTMAP\n"
1589 "#ifdef MODE_VERTEXCOLOR\n"
1590 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1591 "#endif // MODE_VERTEXCOLOR\n"
1592 "#ifdef MODE_FLATCOLOR\n"
1593 " color.rgb = diffusetex * Color_Ambient;\n"
1594 "#endif // MODE_FLATCOLOR\n"
1600 "# ifdef USEDIFFUSE\n"
1601 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1602 "# ifdef USESPECULAR\n"
1603 "# ifdef USEEXACTSPECULARMATH\n"
1604 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1606 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1607 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1609 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1611 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1614 " color.rgb = diffusetex * Color_Ambient;\n"
1618 "#ifdef USEDEFERREDLIGHTMAP\n"
1619 " color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1620 " color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1624 "#ifdef USEVERTEXTEXTUREBLEND\n"
1625 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1627 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1632 "#ifdef MODE_LIGHTSOURCE\n"
1633 " color.rgb *= myhalf(FogVertex());\n"
1635 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1639 " // 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"
1640 "#ifdef USEREFLECTION\n"
1641 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1642 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1643 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1644 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1645 " // FIXME temporary hack to detect the case that the reflection\n"
1646 " // gets blackened at edges due to leaving the area that contains actual\n"
1648 " // Remove this 'ack once we have a better way to stop this thing from\n"
1650 " float 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 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1653 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1654 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1655 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1658 " gl_FragColor = vec4(color);\n"
1660 "#endif // FRAGMENT_SHADER\n"
1662 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1663 "#endif // !MODE_DEFERREDGEOMETRY\n"
1664 "#endif // !MODE_WATER\n"
1665 "#endif // !MODE_REFRACTION\n"
1666 "#endif // !MODE_BLOOMBLUR\n"
1667 "#endif // !MODE_GENERIC\n"
1668 "#endif // !MODE_POSTPROCESS\n"
1669 "#endif // !MODE_SHOWDEPTH\n"
1670 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1674 =========================================================================================================================================================
1678 =========================================================================================================================================================
1682 =========================================================================================================================================================
1686 =========================================================================================================================================================
1690 =========================================================================================================================================================
1694 =========================================================================================================================================================
1698 =========================================================================================================================================================
1701 const char *builtincgshaderstring =
1702 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1703 "// written by Forest 'LordHavoc' Hale\n"
1704 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1706 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1709 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1710 "#define USELIGHTMAP\n"
1712 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1713 "#define USEEYEVECTOR\n"
1716 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1717 "#ifdef VERTEX_SHADER\n"
1720 "float4 gl_Vertex : POSITION,\n"
1721 "uniform float4x4 ModelViewProjectionMatrix,\n"
1722 "out float4 gl_Position : POSITION\n"
1725 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1728 "#else // !MODE_DEPTH_ORSHADOW\n"
1733 "#ifdef MODE_SHOWDEPTH\n"
1734 "#ifdef VERTEX_SHADER\n"
1737 "float4 gl_Vertex : POSITION,\n"
1738 "uniform float4x4 ModelViewProjectionMatrix,\n"
1739 "out float4 gl_Position : POSITION,\n"
1740 "out float4 gl_FrontColor : COLOR0\n"
1743 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1744 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1748 "#ifdef FRAGMENT_SHADER\n"
1751 "float4 gl_FrontColor : COLOR0,\n"
1752 "out float4 gl_FragColor : COLOR\n"
1755 " gl_FragColor = gl_FrontColor;\n"
1758 "#else // !MODE_SHOWDEPTH\n"
1763 "#ifdef MODE_POSTPROCESS\n"
1765 "#ifdef VERTEX_SHADER\n"
1768 "float4 gl_Vertex : POSITION,\n"
1769 "uniform float4x4 ModelViewProjectionMatrix,\n"
1770 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1771 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1772 "out float4 gl_Position : POSITION,\n"
1773 "out float2 TexCoord1 : TEXCOORD0,\n"
1774 "out float2 TexCoord2 : TEXCOORD1\n"
1777 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1778 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1780 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1785 "#ifdef FRAGMENT_SHADER\n"
1788 "float2 TexCoord1 : TEXCOORD0,\n"
1789 "float2 TexCoord2 : TEXCOORD1,\n"
1790 "uniform sampler2D Texture_First,\n"
1792 "uniform sampler2D Texture_Second,\n"
1794 "#ifdef USEGAMMARAMPS\n"
1795 "uniform sampler2D Texture_GammaRamps,\n"
1797 "#ifdef USESATURATION\n"
1798 "uniform float Saturation,\n"
1800 "#ifdef USEVIEWTINT\n"
1801 "uniform float4 ViewTintColor,\n"
1803 "uniform float4 UserVec1,\n"
1804 "uniform float4 UserVec2,\n"
1805 "uniform float4 UserVec3,\n"
1806 "uniform float4 UserVec4,\n"
1807 "uniform float ClientTime,\n"
1808 "uniform float2 PixelSize,\n"
1809 "out float4 gl_FragColor : COLOR\n"
1812 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1814 " gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1816 "#ifdef USEVIEWTINT\n"
1817 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1820 "#ifdef USEPOSTPROCESSING\n"
1821 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1822 "// 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"
1823 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1824 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1825 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1826 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
1827 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
1828 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1831 "#ifdef USESATURATION\n"
1832 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1833 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1834 " //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1835 " gl_FragColor.rgb = mix(float3(y), gl_FragColor.rgb, Saturation);\n"
1838 "#ifdef USEGAMMARAMPS\n"
1839 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1840 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1841 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1845 "#else // !MODE_POSTPROCESS\n"
1850 "#ifdef MODE_GENERIC\n"
1851 "#ifdef VERTEX_SHADER\n"
1854 "float4 gl_Vertex : POSITION,\n"
1855 "uniform float4x4 ModelViewProjectionMatrix,\n"
1856 "float4 gl_Color : COLOR0,\n"
1857 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1858 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1859 "out float4 gl_Position : POSITION,\n"
1860 "out float4 gl_FrontColor : COLOR,\n"
1861 "out float2 TexCoord1 : TEXCOORD0,\n"
1862 "out float2 TexCoord2 : TEXCOORD1\n"
1865 " gl_FrontColor = gl_Color;\n"
1866 "#ifdef USEDIFFUSE\n"
1867 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1869 "#ifdef USESPECULAR\n"
1870 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1872 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1876 "#ifdef FRAGMENT_SHADER\n"
1880 "float4 gl_FrontColor : COLOR,\n"
1881 "float2 TexCoord1 : TEXCOORD0,\n"
1882 "float2 TexCoord2 : TEXCOORD1,\n"
1883 "#ifdef USEDIFFUSE\n"
1884 "uniform sampler2D Texture_First,\n"
1886 "#ifdef USESPECULAR\n"
1887 "uniform sampler2D Texture_Second,\n"
1889 "out float4 gl_FragColor : COLOR\n"
1892 " gl_FragColor = gl_FrontColor;\n"
1893 "#ifdef USEDIFFUSE\n"
1894 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1897 "#ifdef USESPECULAR\n"
1898 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1899 "# ifdef USECOLORMAPPING\n"
1900 " gl_FragColor *= tex2;\n"
1903 " gl_FragColor += tex2;\n"
1905 "# ifdef USEVERTEXTEXTUREBLEND\n"
1906 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
1911 "#else // !MODE_GENERIC\n"
1916 "#ifdef MODE_BLOOMBLUR\n"
1917 "#ifdef VERTEX_SHADER\n"
1920 "float4 gl_Vertex : POSITION,\n"
1921 "uniform float4x4 ModelViewProjectionMatrix,\n"
1922 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1923 "out float4 gl_Position : POSITION,\n"
1924 "out float2 TexCoord : TEXCOORD0\n"
1927 " TexCoord = gl_MultiTexCoord0.xy;\n"
1928 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1932 "#ifdef FRAGMENT_SHADER\n"
1936 "float2 TexCoord : TEXCOORD0,\n"
1937 "uniform sampler2D Texture_First,\n"
1938 "uniform float4 BloomBlur_Parameters,\n"
1939 "out float4 gl_FragColor : COLOR\n"
1943 " float2 tc = TexCoord;\n"
1944 " float3 color = tex2D(Texture_First, tc).rgb;\n"
1945 " tc += BloomBlur_Parameters.xy;\n"
1946 " for (i = 1;i < SAMPLES;i++)\n"
1948 " color += tex2D(Texture_First, tc).rgb;\n"
1949 " tc += BloomBlur_Parameters.xy;\n"
1951 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1954 "#else // !MODE_BLOOMBLUR\n"
1955 "#ifdef MODE_REFRACTION\n"
1956 "#ifdef VERTEX_SHADER\n"
1959 "float4 gl_Vertex : POSITION,\n"
1960 "uniform float4x4 ModelViewProjectionMatrix,\n"
1961 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1962 "uniform mat4 TexMatrix,\n"
1963 "uniform float3 EyePosition,\n"
1964 "out float4 gl_Position : POSITION,\n"
1965 "out float2 TexCoord : TEXCOORD0,\n"
1966 "out float3 EyeVector : TEXCOORD1,\n"
1967 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1970 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1971 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1972 " ModelViewProjectionPosition = gl_Position;\n"
1976 "#ifdef FRAGMENT_SHADER\n"
1979 "float2 TexCoord : TEXCOORD0,\n"
1980 "float3 EyeVector : TEXCOORD1,\n"
1981 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1982 "uniform sampler2D Texture_Normal,\n"
1983 "uniform sampler2D Texture_Refraction,\n"
1984 "uniform sampler2D Texture_Reflection,\n"
1985 "uniform float4 DistortScaleRefractReflect,\n"
1986 "uniform float4 ScreenScaleRefractReflect,\n"
1987 "uniform float4 ScreenCenterRefractReflect,\n"
1988 "uniform float4 RefractColor,\n"
1989 "out float4 gl_FragColor : COLOR\n"
1992 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1993 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1994 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1995 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1996 " // FIXME temporary hack to detect the case that the reflection\n"
1997 " // gets blackened at edges due to leaving the area that contains actual\n"
1999 " // Remove this 'ack once we have a better way to stop this thing from\n"
2001 " float 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 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2004 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2005 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2006 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2009 "#else // !MODE_REFRACTION\n"
2014 "#ifdef MODE_WATER\n"
2015 "#ifdef VERTEX_SHADER\n"
2019 "float4 gl_Vertex : POSITION,\n"
2020 "uniform float4x4 ModelViewProjectionMatrix,\n"
2021 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2022 "uniform mat4 TexMatrix,\n"
2023 "uniform float3 EyePosition,\n"
2024 "out float4 gl_Position : POSITION,\n"
2025 "out float2 TexCoord : TEXCOORD0,\n"
2026 "out float3 EyeVector : TEXCOORD1,\n"
2027 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2030 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2031 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2032 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2033 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2034 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2035 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2036 " ModelViewProjectionPosition = gl_Position;\n"
2040 "#ifdef FRAGMENT_SHADER\n"
2043 "float2 TexCoord : TEXCOORD0,\n"
2044 "float3 EyeVector : TEXCOORD1,\n"
2045 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2046 "uniform sampler2D Texture_Normal,\n"
2047 "uniform sampler2D Texture_Refraction,\n"
2048 "uniform sampler2D Texture_Reflection,\n"
2049 "uniform float4 DistortScaleRefractReflect,\n"
2050 "uniform float4 ScreenScaleRefractReflect,\n"
2051 "uniform float4 ScreenCenterRefractReflect,\n"
2052 "uniform float4 RefractColor,\n"
2053 "uniform float4 ReflectColor,\n"
2054 "uniform float ReflectFactor,\n"
2055 "uniform float ReflectOffset,\n"
2056 "out float4 gl_FragColor : COLOR\n"
2059 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2060 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2061 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2062 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2063 " // FIXME temporary hack to detect the case that the reflection\n"
2064 " // gets blackened at edges due to leaving the area that contains actual\n"
2066 " // Remove this 'ack once we have a better way to stop this thing from\n"
2068 " float 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 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2071 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2072 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\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 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2076 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2077 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2078 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2079 " gl_FragColor = mix(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2082 "#else // !MODE_WATER\n"
2087 "// 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"
2089 "// fragment shader specific:\n"
2090 "#ifdef FRAGMENT_SHADER\n"
2093 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2096 "#ifdef USEFOGOUTSIDE\n"
2097 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2099 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2101 " return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2105 "#ifdef USEOFFSETMAPPING\n"
2106 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2108 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2109 " // 14 sample relief mapping: linear search and then binary search\n"
2110 " // this basically steps forward a small amount repeatedly until it finds\n"
2111 " // itself inside solid, then jitters forward and back using decreasing\n"
2112 " // amounts to find the impact\n"
2113 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2114 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2115 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2116 " float3 RT = float3(TexCoord, 1);\n"
2117 " OffsetVector *= 0.1;\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);\n"
2126 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2127 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2128 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2129 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2130 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2131 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2134 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2135 " // this basically moves forward the full distance, and then backs up based\n"
2136 " // on height of samples\n"
2137 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2138 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2139 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2140 " TexCoord += OffsetVector;\n"
2141 " OffsetVector *= 0.333;\n"
2142 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2143 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2144 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2145 " return TexCoord;\n"
2148 "#endif // USEOFFSETMAPPING\n"
2150 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2151 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2152 "# ifndef USESHADOWMAPVSDCT\n"
2153 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2155 " float3 adir = abs(dir);\n"
2159 " if (adir.x > adir.y)\n"
2161 " if (adir.x > adir.z) // X\n"
2165 " offset = float2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2171 " offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2176 " if (adir.y > adir.z) // Y\n"
2180 " offset = float2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2186 " offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2190 " float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2191 " stc.xy += offset * ShadowMap_Parameters.y;\n"
2192 " stc.z += ShadowMap_Parameters.z;\n"
2196 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2198 " float3 adir = abs(dir);\n"
2199 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2200 " float ma = max(max(adir.x, adir.y), adir.z);\n"
2201 " float3 stc = float3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2202 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2203 " stc.z += ShadowMap_Parameters.z;\n"
2207 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2209 "#ifdef USESHADOWMAPCUBE\n"
2210 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2212 " float3 adir = abs(dir);\n"
2213 " return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2217 "# ifdef USESHADOWMAPRECT\n"
2218 "#ifdef USESHADOWMAPVSDCT\n"
2219 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2221 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2224 "#ifdef USESHADOWMAPVSDCT\n"
2225 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2227 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2230 "# ifdef USESHADOWSAMPLER\n"
2232 "# ifdef USESHADOWMAPPCF\n"
2233 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2234 " 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"
2236 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2241 "# ifdef USESHADOWMAPPCF\n"
2242 "# if USESHADOWMAPPCF > 1\n"
2243 "# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2244 " float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2245 " 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"
2246 " 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"
2247 " 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"
2248 " 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"
2249 " float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2250 " f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2252 "# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2253 " float2 offset = fract(shadowmaptc.xy);\n"
2254 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2255 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2256 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2257 " float3 cols = row2 + mix(row1, row3, offset.y);\n"
2258 " f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2261 " f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2269 "# ifdef USESHADOWMAP2D\n"
2270 "#ifdef USESHADOWMAPVSDCT\n"
2271 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2273 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2276 "#ifdef USESHADOWMAPVSDCT\n"
2277 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2279 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2283 "# ifdef USESHADOWSAMPLER\n"
2284 "# ifdef USESHADOWMAPPCF\n"
2285 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
2286 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2287 " 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"
2289 " f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2292 "# ifdef USESHADOWMAPPCF\n"
2293 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2294 "# ifdef GL_ARB_texture_gather\n"
2295 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2297 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2299 " float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2300 " center *= ShadowMap_TextureScale;\n"
2301 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2302 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2303 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2304 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2305 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2306 " mix(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2307 " f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2309 "# ifdef GL_EXT_gpu_shader4\n"
2310 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, ifloat2(x, y)).r\n"
2312 "# define texval(x, y) tex2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2314 "# if USESHADOWMAPPCF > 1\n"
2315 " float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2316 " center *= ShadowMap_TextureScale;\n"
2317 " 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"
2318 " 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"
2319 " 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"
2320 " 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"
2321 " float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2322 " f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2324 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
2325 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2326 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2327 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2328 " float3 cols = row2 + mix(row1, row3, offset.y);\n"
2329 " f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2333 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2340 "# ifdef USESHADOWMAPCUBE\n"
2341 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2343 " // apply depth texture cubemap as light filter\n"
2344 " float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2346 "# ifdef USESHADOWSAMPLER\n"
2347 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2349 " f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2354 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2355 "#endif // FRAGMENT_SHADER\n"
2360 "#ifdef MODE_DEFERREDGEOMETRY\n"
2361 "#ifdef VERTEX_SHADER\n"
2364 "float4 gl_Vertex : POSITION,\n"
2365 "uniform float4x4 ModelViewProjectionMatrix,\n"
2366 "#ifdef USEVERTEXTEXTUREBLEND\n"
2367 "float4 gl_Color : COLOR0,\n"
2369 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2370 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2371 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2372 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2373 "uniform mat4 TexMatrix,\n"
2374 "#ifdef USEVERTEXTEXTUREBLEND\n"
2375 "uniform mat4 BackgroundTexMatrix,\n"
2377 "uniform mat4 ModelViewMatrix,\n"
2378 "out float4 gl_Position : POSITION,\n"
2379 "out float4 gl_FrontColor : COLOR,\n"
2380 "out float4 TexCoordBoth : TEXCOORD0,\n"
2381 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2382 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2383 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2386 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2387 "#ifdef USEVERTEXTEXTUREBLEND\n"
2388 " gl_FrontColor = gl_Color;\n"
2389 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2392 " // transform unnormalized eye direction into tangent space\n"
2393 "#ifdef USEOFFSETMAPPING\n"
2394 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2395 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2396 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2397 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2400 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2401 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2402 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2403 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2405 "#endif // VERTEX_SHADER\n"
2407 "#ifdef FRAGMENT_SHADER\n"
2410 "float4 TexCoordBoth : TEXCOORD0,\n"
2411 "float3 EyeVector : TEXCOORD2,\n"
2412 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2413 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2414 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2415 "uniform sampler2D Texture_Normal,\n"
2416 "#ifdef USEALPHAKILL\n"
2417 "uniform sampler2D Texture_Color,\n"
2419 "#ifdef USEVERTEXTEXTUREBLEND\n"
2420 "uniform sampler2D Texture_SecondaryNormal,\n"
2422 "#ifdef USEOFFSETMAPPING\n"
2423 "uniform float OffsetMapping_Scale,\n"
2425 "uniform half SpecularPower,\n"
2426 "out float4 gl_FragColor : COLOR\n"
2429 " float2 TexCoord = TexCoordBoth.xy;\n"
2430 "#ifdef USEOFFSETMAPPING\n"
2431 " // apply offsetmapping\n"
2432 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2433 "#define TexCoord TexCoordOffset\n"
2436 "#ifdef USEALPHAKILL\n"
2437 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2441 "#ifdef USEVERTEXTEXTUREBLEND\n"
2442 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2443 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2444 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2445 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2448 "#ifdef USEVERTEXTEXTUREBLEND\n"
2449 " float3 surfacenormal = mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2451 " float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2454 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2456 "#endif // FRAGMENT_SHADER\n"
2457 "#else // !MODE_DEFERREDGEOMETRY\n"
2462 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2463 "#ifdef VERTEX_SHADER\n"
2466 "float4 gl_Vertex : POSITION,\n"
2467 "uniform float4x4 ModelViewProjectionMatrix,\n"
2468 "uniform mat4 ModelViewMatrix,\n"
2469 "out float4 gl_Position : POSITION,\n"
2470 "out float4 ModelViewPosition : TEXCOORD0\n"
2473 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2474 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2476 "#endif // VERTEX_SHADER\n"
2478 "#ifdef FRAGMENT_SHADER\n"
2481 "float2 Pixel : WPOS,\n"
2482 "float4 ModelViewPosition : TEXCOORD0,\n"
2483 "uniform mat4 ViewToLight,\n"
2484 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2485 "uniform float3 LightPosition,\n"
2486 "uniform half3 DeferredColor_Ambient,\n"
2487 "uniform half3 DeferredColor_Diffuse,\n"
2488 "#ifdef USESPECULAR\n"
2489 "uniform half3 DeferredColor_Specular,\n"
2490 "uniform half SpecularPower,\n"
2492 "uniform sampler2D Texture_Attenuation,\n"
2493 "uniform samplerRECT Texture_ScreenDepth,\n"
2494 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2496 "#ifdef USESHADOWMAPRECT\n"
2497 "# ifdef USESHADOWSAMPLER\n"
2498 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2500 "uniform samplerRECT Texture_ShadowMapRect,\n"
2504 "#ifdef USESHADOWMAP2D\n"
2505 "# ifdef USESHADOWSAMPLER\n"
2506 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2508 "uniform sampler2D Texture_ShadowMap2D,\n"
2512 "#ifdef USESHADOWMAPVSDCT\n"
2513 "uniform samplerCUBE Texture_CubeProjection,\n"
2516 "#ifdef USESHADOWMAPCUBE\n"
2517 "# ifdef USESHADOWSAMPLER\n"
2518 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2520 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2524 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2525 "uniform float2 ShadowMap_TextureScale,\n"
2526 "uniform float4 ShadowMap_Parameters,\n"
2529 "out float4 gl_FragData0 : COLOR0,\n"
2530 "out float4 gl_FragData1 : COLOR1\n"
2533 " // calculate viewspace pixel position\n"
2534 " float3 position;\n"
2535 " position.z = ScreenToDepth.y / (texRECT(Texture_ScreenDepth, Pixel).r + ScreenToDepth.x);\n"
2536 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2537 " // decode viewspace pixel normal\n"
2538 " half4 normalmap = texRECT(Texture_ScreenNormalMap, Pixel);\n"
2539 " half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2540 " // surfacenormal = pixel normal in viewspace\n"
2541 " // LightVector = pixel to light in viewspace\n"
2542 " // CubeVector = position in lightspace\n"
2543 " // eyevector = pixel to view in viewspace\n"
2544 " float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2545 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2546 "#ifdef USEDIFFUSE\n"
2547 " // calculate diffuse shading\n"
2548 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2549 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2551 "#ifdef USESPECULAR\n"
2552 " // calculate directional shading\n"
2553 " float3 eyevector = position * -1.0;\n"
2554 "# ifdef USEEXACTSPECULARMATH\n"
2555 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2557 " half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2558 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2562 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2563 " fade *= ShadowMapCompare(CubeVector,\n"
2564 "# if defined(USESHADOWMAP2D)\n"
2565 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2567 "# if defined(USESHADOWMAPRECT)\n"
2568 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2570 "# if defined(USESHADOWMAPCUBE)\n"
2571 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2574 "#ifdef USESHADOWMAPVSDCT\n"
2575 ", Texture_CubeProjection\n"
2580 "#ifdef USEDIFFUSE\n"
2581 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2583 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2585 "#ifdef USESPECULAR\n"
2586 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2588 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2591 "# ifdef USECUBEFILTER\n"
2592 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2593 " gl_FragData0.rgb *= cubecolor;\n"
2594 " gl_FragData1.rgb *= cubecolor;\n"
2597 "#endif // FRAGMENT_SHADER\n"
2598 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2603 "#ifdef VERTEX_SHADER\n"
2606 "float4 gl_Vertex : POSITION,\n"
2607 "uniform float4x4 ModelViewProjectionMatrix,\n"
2608 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2609 "float4 gl_Color : COLOR0,\n"
2611 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2612 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2613 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2614 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2615 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2617 "uniform float3 EyePosition,\n"
2618 "uniform mat4 TexMatrix,\n"
2619 "#ifdef USEVERTEXTEXTUREBLEND\n"
2620 "uniform mat4 BackgroundTexMatrix,\n"
2622 "#ifdef MODE_LIGHTSOURCE\n"
2623 "uniform mat4 ModelToLight,\n"
2625 "#ifdef MODE_LIGHTSOURCE\n"
2626 "uniform float3 LightPosition,\n"
2628 "#ifdef MODE_LIGHTDIRECTION\n"
2629 "uniform float3 LightDir,\n"
2631 "uniform float4 FogPlane,\n"
2632 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2633 "uniform float3 LightPosition,\n"
2636 "out float4 gl_FrontColor : COLOR,\n"
2637 "out float4 TexCoordBoth : TEXCOORD0,\n"
2638 "#ifdef USELIGHTMAP\n"
2639 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2641 "#ifdef USEEYEVECTOR\n"
2642 "out float3 EyeVector : TEXCOORD2,\n"
2644 "#ifdef USEREFLECTION\n"
2645 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2648 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2650 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2651 "out float3 LightVector : TEXCOORD5,\n"
2653 "#ifdef MODE_LIGHTSOURCE\n"
2654 "out float3 CubeVector : TEXCOORD3,\n"
2656 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2657 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2658 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2659 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2661 "out float4 gl_Position : POSITION\n"
2664 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2665 " gl_FrontColor = gl_Color;\n"
2667 " // copy the surface texcoord\n"
2668 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2669 "#ifdef USEVERTEXTEXTUREBLEND\n"
2670 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2672 "#ifdef USELIGHTMAP\n"
2673 " TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2676 "#ifdef MODE_LIGHTSOURCE\n"
2677 " // transform vertex position into light attenuation/cubemap space\n"
2678 " // (-1 to +1 across the light box)\n"
2679 " CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2681 "# ifdef USEDIFFUSE\n"
2682 " // transform unnormalized light direction into tangent space\n"
2683 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2684 " // normalize it per pixel)\n"
2685 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2686 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2687 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2688 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2692 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2693 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2694 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2695 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2698 " // transform unnormalized eye direction into tangent space\n"
2699 "#ifdef USEEYEVECTOR\n"
2700 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2701 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2702 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2703 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2707 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2708 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2711 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2712 " VectorS = gl_MultiTexCoord1.xyz;\n"
2713 " VectorT = gl_MultiTexCoord2.xyz;\n"
2714 " VectorR = gl_MultiTexCoord3.xyz;\n"
2717 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2718 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2720 "#ifdef USEREFLECTION\n"
2721 " ModelViewProjectionPosition = gl_Position;\n"
2724 "#endif // VERTEX_SHADER\n"
2729 "#ifdef FRAGMENT_SHADER\n"
2732 "#ifdef USEDEFERREDLIGHTMAP\n"
2733 "float2 Pixel : WPOS,\n"
2735 "float4 gl_FrontColor : COLOR,\n"
2736 "float4 TexCoordBoth : TEXCOORD0,\n"
2737 "#ifdef USELIGHTMAP\n"
2738 "float2 TexCoordLightmap : TEXCOORD1,\n"
2740 "#ifdef USEEYEVECTOR\n"
2741 "float3 EyeVector : TEXCOORD2,\n"
2743 "#ifdef USEREFLECTION\n"
2744 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2747 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2749 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2750 "float3 LightVector : TEXCOORD5,\n"
2752 "#ifdef MODE_LIGHTSOURCE\n"
2753 "float3 CubeVector : TEXCOORD3,\n"
2755 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2756 "float4 ModelViewPosition : TEXCOORD0,\n"
2758 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2759 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2760 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2761 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2764 "uniform sampler2D Texture_Normal,\n"
2765 "uniform sampler2D Texture_Color,\n"
2766 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2767 "uniform sampler2D Texture_Gloss,\n"
2770 "uniform sampler2D Texture_Glow,\n"
2772 "#ifdef USEVERTEXTEXTUREBLEND\n"
2773 "uniform sampler2D Texture_SecondaryNormal,\n"
2774 "uniform sampler2D Texture_SecondaryColor,\n"
2775 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2776 "uniform sampler2D Texture_SecondaryGloss,\n"
2779 "uniform sampler2D Texture_SecondaryGlow,\n"
2782 "#ifdef USECOLORMAPPING\n"
2783 "uniform sampler2D Texture_Pants,\n"
2784 "uniform sampler2D Texture_Shirt,\n"
2787 "uniform sampler2D Texture_FogMask,\n"
2789 "#ifdef USELIGHTMAP\n"
2790 "uniform sampler2D Texture_Lightmap,\n"
2792 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2793 "uniform sampler2D Texture_Deluxemap,\n"
2795 "#ifdef USEREFLECTION\n"
2796 "uniform sampler2D Texture_Reflection,\n"
2799 "//#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2800 "uniform samplerRECT Texture_ScreenDepth,\n"
2801 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2803 "#ifdef USEDEFERREDLIGHTMAP\n"
2804 "uniform samplerRECT Texture_ScreenDiffuse,\n"
2805 "uniform samplerRECT Texture_ScreenSpecular,\n"
2808 "#ifdef USECOLORMAPPING\n"
2809 "uniform half3 Color_Pants,\n"
2810 "uniform half3 Color_Shirt,\n"
2813 "uniform float3 FogColor,\n"
2814 "uniform float FogRangeRecip,\n"
2815 "uniform float FogPlaneViewDist,\n"
2816 "uniform float FogHeightFade,\n"
2819 "#ifdef USEOFFSETMAPPING\n"
2820 "uniform float OffsetMapping_Scale,\n"
2823 "#ifdef USEDEFERREDLIGHTMAP\n"
2824 "uniform half3 DeferredMod_Diffuse,\n"
2825 "uniform half3 DeferredMod_Specular,\n"
2827 "uniform half3 Color_Ambient,\n"
2828 "uniform half3 Color_Diffuse,\n"
2829 "uniform half3 Color_Specular,\n"
2830 "uniform half SpecularPower,\n"
2832 "uniform half3 Color_Glow,\n"
2834 "uniform half Alpha,\n"
2835 "#ifdef USEREFLECTION\n"
2836 "uniform float4 DistortScaleRefractReflect,\n"
2837 "uniform float4 ScreenScaleRefractReflect,\n"
2838 "uniform float4 ScreenCenterRefractReflect,\n"
2839 "uniform half4 ReflectColor,\n"
2841 "#ifdef MODE_LIGHTDIRECTION\n"
2842 "uniform half3 LightColor,\n"
2844 "#ifdef MODE_LIGHTSOURCE\n"
2845 "uniform half3 LightColor,\n"
2848 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2849 "uniform sampler2D Texture_Attenuation,\n"
2850 "uniform samplerCUBE Texture_Cube,\n"
2852 "#ifdef USESHADOWMAPRECT\n"
2853 "# ifdef USESHADOWSAMPLER\n"
2854 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2856 "uniform samplerRECT Texture_ShadowMapRect,\n"
2860 "#ifdef USESHADOWMAP2D\n"
2861 "# ifdef USESHADOWSAMPLER\n"
2862 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2864 "uniform sampler2D Texture_ShadowMap2D,\n"
2868 "#ifdef USESHADOWMAPVSDCT\n"
2869 "uniform samplerCUBE Texture_CubeProjection,\n"
2872 "#ifdef USESHADOWMAPCUBE\n"
2873 "# ifdef USESHADOWSAMPLER\n"
2874 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2876 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2880 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2881 "uniform float2 ShadowMap_TextureScale,\n"
2882 "uniform float4 ShadowMap_Parameters,\n"
2884 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2886 "out float4 gl_FragColor : COLOR\n"
2889 " float2 TexCoord = TexCoordBoth.xy;\n"
2890 "#ifdef USEVERTEXTEXTUREBLEND\n"
2891 " float2 TexCoord2 = TexCoordBoth.zw;\n"
2893 "#ifdef USEOFFSETMAPPING\n"
2894 " // apply offsetmapping\n"
2895 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2896 "#define TexCoord TexCoordOffset\n"
2899 " // combine the diffuse textures (base, pants, shirt)\n"
2900 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2901 "#ifdef USEALPHAKILL\n"
2902 " if (color.a < 0.5)\n"
2905 " color.a *= Alpha;\n"
2906 "#ifdef USECOLORMAPPING\n"
2907 " color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2909 "#ifdef USEVERTEXTEXTUREBLEND\n"
2910 " float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2911 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2912 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2913 " color.rgb = half3(mix(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2915 " //color = mix(half4(1, 0, 0, 1), color, terrainblend);\n"
2918 " // get the surface normal\n"
2919 "#ifdef USEVERTEXTEXTUREBLEND\n"
2920 " half3 surfacenormal = normalize(half3(mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2922 " half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2925 " // get the material colors\n"
2926 " half3 diffusetex = color.rgb;\n"
2927 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2928 "# ifdef USEVERTEXTEXTUREBLEND\n"
2929 " half3 glosstex = half3(mix(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2931 " half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2938 "#ifdef MODE_LIGHTSOURCE\n"
2939 " // light source\n"
2940 " half3 lightnormal = half3(normalize(LightVector));\n"
2941 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2942 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2943 "#ifdef USESPECULAR\n"
2944 "#ifdef USEEXACTSPECULARMATH\n"
2945 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2947 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2948 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2950 " color.rgb += glosstex * (specular * Color_Specular);\n"
2952 " color.rgb *= LightColor;\n"
2953 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2954 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2955 " color.rgb *= ShadowMapCompare(CubeVector,\n"
2956 "# if defined(USESHADOWMAP2D)\n"
2957 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2959 "# if defined(USESHADOWMAPRECT)\n"
2960 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2962 "# if defined(USESHADOWMAPCUBE)\n"
2963 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2966 "#ifdef USESHADOWMAPVSDCT\n"
2967 ", Texture_CubeProjection\n"
2972 "# ifdef USECUBEFILTER\n"
2973 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2975 "#endif // MODE_LIGHTSOURCE\n"
2980 "#ifdef MODE_LIGHTDIRECTION\n"
2982 "#ifdef USEDIFFUSE\n"
2983 " half3 lightnormal = half3(normalize(LightVector));\n"
2985 "#define lightcolor LightColor\n"
2986 "#endif // MODE_LIGHTDIRECTION\n"
2987 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2989 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
2990 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
2991 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
2992 " // convert modelspace light vector to tangentspace\n"
2993 " half3 lightnormal;\n"
2994 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
2995 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
2996 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
2997 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
2998 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
2999 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3000 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3001 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3002 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3003 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3004 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3005 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3006 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3007 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3008 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3010 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3011 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3012 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3018 "#ifdef MODE_LIGHTMAP\n"
3019 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3020 "#endif // MODE_LIGHTMAP\n"
3021 "#ifdef MODE_VERTEXCOLOR\n"
3022 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3023 "#endif // MODE_VERTEXCOLOR\n"
3024 "#ifdef MODE_FLATCOLOR\n"
3025 " color.rgb = diffusetex * Color_Ambient;\n"
3026 "#endif // MODE_FLATCOLOR\n"
3032 "# ifdef USEDIFFUSE\n"
3033 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3034 "# ifdef USESPECULAR\n"
3035 "# ifdef USEEXACTSPECULARMATH\n"
3036 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3038 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3039 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3041 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3043 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3046 " color.rgb = diffusetex * Color_Ambient;\n"
3050 "#ifdef USEDEFERREDLIGHTMAP\n"
3051 " color.rgb += diffusetex * half3(texRECT(Texture_ScreenDiffuse, Pixel)) * DeferredMod_Diffuse;\n"
3052 " color.rgb += glosstex * half3(texRECT(Texture_ScreenSpecular, Pixel)) * DeferredMod_Specular;\n"
3053 " color.rgb = half3(texRECT(Texture_ScreenDepth, Pixel));\n"
3057 "#ifdef USEVERTEXTEXTUREBLEND\n"
3058 " color.rgb += mix(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3060 " color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3065 "#ifdef MODE_LIGHTSOURCE\n"
3066 " color.rgb *= half(FogVertex());\n"
3068 " color.rgb = mix(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3072 " // 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"
3073 "#ifdef USEREFLECTION\n"
3074 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3075 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3076 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3077 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3078 " // FIXME temporary hack to detect the case that the reflection\n"
3079 " // gets blackened at edges due to leaving the area that contains actual\n"
3081 " // Remove this 'ack once we have a better way to stop this thing from\n"
3083 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3084 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3085 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3086 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3087 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3088 " color.rgb = mix(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3091 " gl_FragColor = float4(color);\n"
3093 "#endif // FRAGMENT_SHADER\n"
3095 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3096 "#endif // !MODE_DEFERREDGEOMETRY\n"
3097 "#endif // !MODE_WATER\n"
3098 "#endif // !MODE_REFRACTION\n"
3099 "#endif // !MODE_BLOOMBLUR\n"
3100 "#endif // !MODE_GENERIC\n"
3101 "#endif // !MODE_POSTPROCESS\n"
3102 "#endif // !MODE_SHOWDEPTH\n"
3103 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3106 //=======================================================================================================================================================
3108 typedef struct shaderpermutationinfo_s
3110 const char *pretext;
3113 shaderpermutationinfo_t;
3115 typedef struct shadermodeinfo_s
3117 const char *vertexfilename;
3118 const char *geometryfilename;
3119 const char *fragmentfilename;
3120 const char *pretext;
3125 typedef enum shaderpermutation_e
3127 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3128 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3129 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3130 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3131 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3132 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3133 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3134 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3135 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3136 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3137 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3138 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3139 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3140 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3141 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3142 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3143 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3144 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3145 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3146 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3147 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3148 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3149 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3150 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3151 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3152 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3153 SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3154 SHADERPERMUTATION_COUNT = 26 ///< size of shaderpermutationinfo array
3156 shaderpermutation_t;
3158 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3159 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3161 {"#define USEDIFFUSE\n", " diffuse"},
3162 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3163 {"#define USEVIEWTINT\n", " viewtint"},
3164 {"#define USECOLORMAPPING\n", " colormapping"},
3165 {"#define USESATURATION\n", " saturation"},
3166 {"#define USEFOGINSIDE\n", " foginside"},
3167 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3168 {"#define USEGAMMARAMPS\n", " gammaramps"},
3169 {"#define USECUBEFILTER\n", " cubefilter"},
3170 {"#define USEGLOW\n", " glow"},
3171 {"#define USEBLOOM\n", " bloom"},
3172 {"#define USESPECULAR\n", " specular"},
3173 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3174 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3175 {"#define USEREFLECTION\n", " reflection"},
3176 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3177 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3178 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3179 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3180 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3181 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3182 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3183 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3184 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3185 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3186 {"#define USEALPHAKILL\n", " alphakill"},
3189 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3190 typedef enum shadermode_e
3192 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3193 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3194 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3195 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3196 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3197 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3198 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3199 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3200 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3201 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3202 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3203 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3204 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3205 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3206 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3211 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3212 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3214 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3215 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3216 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3217 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3218 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3219 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3220 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3221 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3222 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3223 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3224 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3225 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3226 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3227 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3228 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3232 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3234 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3235 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3236 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3237 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3238 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3239 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3240 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3241 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3242 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3243 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3244 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3245 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3246 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3247 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3248 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3252 struct r_glsl_permutation_s;
3253 typedef struct r_glsl_permutation_s
3255 /// hash lookup data
3256 struct r_glsl_permutation_s *hashnext;
3258 unsigned int permutation;
3260 /// indicates if we have tried compiling this permutation already
3262 /// 0 if compilation failed
3264 /// locations of detected uniforms in program object, or -1 if not found
3265 int loc_Texture_First;
3266 int loc_Texture_Second;
3267 int loc_Texture_GammaRamps;
3268 int loc_Texture_Normal;
3269 int loc_Texture_Color;
3270 int loc_Texture_Gloss;
3271 int loc_Texture_Glow;
3272 int loc_Texture_SecondaryNormal;
3273 int loc_Texture_SecondaryColor;
3274 int loc_Texture_SecondaryGloss;
3275 int loc_Texture_SecondaryGlow;
3276 int loc_Texture_Pants;
3277 int loc_Texture_Shirt;
3278 int loc_Texture_FogMask;
3279 int loc_Texture_Lightmap;
3280 int loc_Texture_Deluxemap;
3281 int loc_Texture_Attenuation;
3282 int loc_Texture_Cube;
3283 int loc_Texture_Refraction;
3284 int loc_Texture_Reflection;
3285 int loc_Texture_ShadowMapRect;
3286 int loc_Texture_ShadowMapCube;
3287 int loc_Texture_ShadowMap2D;
3288 int loc_Texture_CubeProjection;
3289 int loc_Texture_ScreenDepth;
3290 int loc_Texture_ScreenNormalMap;
3291 int loc_Texture_ScreenDiffuse;
3292 int loc_Texture_ScreenSpecular;
3294 int loc_BloomBlur_Parameters;
3296 int loc_Color_Ambient;
3297 int loc_Color_Diffuse;
3298 int loc_Color_Specular;
3300 int loc_Color_Pants;
3301 int loc_Color_Shirt;
3302 int loc_DeferredColor_Ambient;
3303 int loc_DeferredColor_Diffuse;
3304 int loc_DeferredColor_Specular;
3305 int loc_DeferredMod_Diffuse;
3306 int loc_DeferredMod_Specular;
3307 int loc_DistortScaleRefractReflect;
3308 int loc_EyePosition;
3310 int loc_FogHeightFade;
3312 int loc_FogPlaneViewDist;
3313 int loc_FogRangeRecip;
3316 int loc_LightPosition;
3317 int loc_OffsetMapping_Scale;
3319 int loc_ReflectColor;
3320 int loc_ReflectFactor;
3321 int loc_ReflectOffset;
3322 int loc_RefractColor;
3324 int loc_ScreenCenterRefractReflect;
3325 int loc_ScreenScaleRefractReflect;
3326 int loc_ScreenToDepth;
3327 int loc_ShadowMap_Parameters;
3328 int loc_ShadowMap_TextureScale;
3329 int loc_SpecularPower;
3334 int loc_ViewTintColor;
3335 int loc_ViewToLight;
3336 int loc_ModelToLight;
3338 int loc_BackgroundTexMatrix;
3339 int loc_ModelViewProjectionMatrix;
3340 int loc_ModelViewMatrix;
3342 r_glsl_permutation_t;
3344 #define SHADERPERMUTATION_HASHSIZE 256
3346 /// information about each possible shader permutation
3347 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3348 /// currently selected permutation
3349 r_glsl_permutation_t *r_glsl_permutation;
3350 /// storage for permutations linked in the hash table
3351 memexpandablearray_t r_glsl_permutationarray;
3353 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3355 //unsigned int hashdepth = 0;
3356 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3357 r_glsl_permutation_t *p;
3358 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3360 if (p->mode == mode && p->permutation == permutation)
3362 //if (hashdepth > 10)
3363 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3368 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3370 p->permutation = permutation;
3371 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3372 r_glsl_permutationhash[mode][hashindex] = p;
3373 //if (hashdepth > 10)
3374 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3378 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3381 if (!filename || !filename[0])
3383 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3386 if (printfromdisknotice)
3387 Con_DPrintf("from disk %s... ", filename);
3388 return shaderstring;
3390 else if (!strcmp(filename, "glsl/default.glsl"))
3392 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3393 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3395 return shaderstring;
3398 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3401 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3402 int vertstrings_count = 0;
3403 int geomstrings_count = 0;
3404 int fragstrings_count = 0;
3405 char *vertexstring, *geometrystring, *fragmentstring;
3406 const char *vertstrings_list[32+3];
3407 const char *geomstrings_list[32+3];
3408 const char *fragstrings_list[32+3];
3409 char permutationname[256];
3416 permutationname[0] = 0;
3417 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3418 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3419 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3421 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3423 // the first pretext is which type of shader to compile as
3424 // (later these will all be bound together as a program object)
3425 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3426 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3427 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3429 // the second pretext is the mode (for example a light source)
3430 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3431 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3432 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3433 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3435 // now add all the permutation pretexts
3436 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3438 if (permutation & (1<<i))
3440 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3441 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3442 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3443 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3447 // keep line numbers correct
3448 vertstrings_list[vertstrings_count++] = "\n";
3449 geomstrings_list[geomstrings_count++] = "\n";
3450 fragstrings_list[fragstrings_count++] = "\n";
3454 // now append the shader text itself
3455 vertstrings_list[vertstrings_count++] = vertexstring;
3456 geomstrings_list[geomstrings_count++] = geometrystring;
3457 fragstrings_list[fragstrings_count++] = fragmentstring;
3459 // if any sources were NULL, clear the respective list
3461 vertstrings_count = 0;
3462 if (!geometrystring)
3463 geomstrings_count = 0;
3464 if (!fragmentstring)
3465 fragstrings_count = 0;
3467 // compile the shader program
3468 if (vertstrings_count + geomstrings_count + fragstrings_count)
3469 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3473 qglUseProgramObjectARB(p->program);CHECKGLERROR
3474 // look up all the uniform variable names we care about, so we don't
3475 // have to look them up every time we set them
3477 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3478 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3479 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3480 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3481 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3482 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3483 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3484 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3485 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3486 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3487 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3488 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3489 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3490 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3491 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3492 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3493 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3494 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3495 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3496 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3497 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3498 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3499 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3500 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3501 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3502 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3503 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3504 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3505 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3506 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3507 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3508 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3509 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3510 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3511 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3512 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3513 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3514 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3515 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3516 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3517 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3518 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3519 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3520 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3521 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3522 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3523 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3524 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3525 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3526 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3527 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3528 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3529 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3530 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3531 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3532 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3533 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3534 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3535 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3536 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3537 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3538 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3539 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3540 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3541 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3542 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3543 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3544 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3545 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3546 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3547 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3548 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3549 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3550 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3551 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3552 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3553 // initialize the samplers to refer to the texture units we use
3554 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3555 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3556 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3557 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3558 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3559 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3560 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3561 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3562 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3563 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3564 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3565 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3566 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3567 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3568 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3569 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3570 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3571 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3572 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3573 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3574 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
3575 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
3576 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3577 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3578 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3579 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3580 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3581 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3583 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3586 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3590 Mem_Free(vertexstring);
3592 Mem_Free(geometrystring);
3594 Mem_Free(fragmentstring);
3597 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3599 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3600 if (r_glsl_permutation != perm)
3602 r_glsl_permutation = perm;
3603 if (!r_glsl_permutation->program)
3605 if (!r_glsl_permutation->compiled)
3606 R_GLSL_CompilePermutation(perm, mode, permutation);
3607 if (!r_glsl_permutation->program)
3609 // remove features until we find a valid permutation
3611 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3613 // reduce i more quickly whenever it would not remove any bits
3614 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3615 if (!(permutation & j))
3618 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3619 if (!r_glsl_permutation->compiled)
3620 R_GLSL_CompilePermutation(perm, mode, permutation);
3621 if (r_glsl_permutation->program)
3624 if (i >= SHADERPERMUTATION_COUNT)
3626 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3627 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3628 qglUseProgramObjectARB(0);CHECKGLERROR
3629 return; // no bit left to clear, entire mode is broken
3634 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3636 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3637 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3641 #include <Cg/cgGL.h>
3642 struct r_cg_permutation_s;
3643 typedef struct r_cg_permutation_s
3645 /// hash lookup data
3646 struct r_cg_permutation_s *hashnext;
3648 unsigned int permutation;
3650 /// indicates if we have tried compiling this permutation already
3652 /// 0 if compilation failed
3655 /// locations of detected parameters in programs, or NULL if not found
3656 CGparameter vp_EyePosition;
3657 CGparameter vp_FogPlane;
3658 CGparameter vp_LightDir;
3659 CGparameter vp_LightPosition;
3660 CGparameter vp_ModelToLight;
3661 CGparameter vp_TexMatrix;
3662 CGparameter vp_BackgroundTexMatrix;
3663 CGparameter vp_ModelViewProjectionMatrix;
3664 CGparameter vp_ModelViewMatrix;
3666 CGparameter fp_Texture_First;
3667 CGparameter fp_Texture_Second;
3668 CGparameter fp_Texture_GammaRamps;
3669 CGparameter fp_Texture_Normal;
3670 CGparameter fp_Texture_Color;
3671 CGparameter fp_Texture_Gloss;
3672 CGparameter fp_Texture_Glow;
3673 CGparameter fp_Texture_SecondaryNormal;
3674 CGparameter fp_Texture_SecondaryColor;
3675 CGparameter fp_Texture_SecondaryGloss;
3676 CGparameter fp_Texture_SecondaryGlow;
3677 CGparameter fp_Texture_Pants;
3678 CGparameter fp_Texture_Shirt;
3679 CGparameter fp_Texture_FogMask;
3680 CGparameter fp_Texture_Lightmap;
3681 CGparameter fp_Texture_Deluxemap;
3682 CGparameter fp_Texture_Attenuation;
3683 CGparameter fp_Texture_Cube;
3684 CGparameter fp_Texture_Refraction;
3685 CGparameter fp_Texture_Reflection;
3686 CGparameter fp_Texture_ShadowMapRect;
3687 CGparameter fp_Texture_ShadowMapCube;
3688 CGparameter fp_Texture_ShadowMap2D;
3689 CGparameter fp_Texture_CubeProjection;
3690 CGparameter fp_Texture_ScreenDepth;
3691 CGparameter fp_Texture_ScreenNormalMap;
3692 CGparameter fp_Texture_ScreenDiffuse;
3693 CGparameter fp_Texture_ScreenSpecular;
3694 CGparameter fp_Alpha;
3695 CGparameter fp_BloomBlur_Parameters;
3696 CGparameter fp_ClientTime;
3697 CGparameter fp_Color_Ambient;
3698 CGparameter fp_Color_Diffuse;
3699 CGparameter fp_Color_Specular;
3700 CGparameter fp_Color_Glow;
3701 CGparameter fp_Color_Pants;
3702 CGparameter fp_Color_Shirt;
3703 CGparameter fp_DeferredColor_Ambient;
3704 CGparameter fp_DeferredColor_Diffuse;
3705 CGparameter fp_DeferredColor_Specular;
3706 CGparameter fp_DeferredMod_Diffuse;
3707 CGparameter fp_DeferredMod_Specular;
3708 CGparameter fp_DistortScaleRefractReflect;
3709 CGparameter fp_EyePosition;
3710 CGparameter fp_FogColor;
3711 CGparameter fp_FogHeightFade;
3712 CGparameter fp_FogPlane;
3713 CGparameter fp_FogPlaneViewDist;
3714 CGparameter fp_FogRangeRecip;
3715 CGparameter fp_LightColor;
3716 CGparameter fp_LightDir;
3717 CGparameter fp_LightPosition;
3718 CGparameter fp_OffsetMapping_Scale;
3719 CGparameter fp_PixelSize;
3720 CGparameter fp_ReflectColor;
3721 CGparameter fp_ReflectFactor;
3722 CGparameter fp_ReflectOffset;
3723 CGparameter fp_RefractColor;
3724 CGparameter fp_Saturation;
3725 CGparameter fp_ScreenCenterRefractReflect;
3726 CGparameter fp_ScreenScaleRefractReflect;
3727 CGparameter fp_ScreenToDepth;
3728 CGparameter fp_ShadowMap_Parameters;
3729 CGparameter fp_ShadowMap_TextureScale;
3730 CGparameter fp_SpecularPower;
3731 CGparameter fp_UserVec1;
3732 CGparameter fp_UserVec2;
3733 CGparameter fp_UserVec3;
3734 CGparameter fp_UserVec4;
3735 CGparameter fp_ViewTintColor;
3736 CGparameter fp_ViewToLight;
3740 /// information about each possible shader permutation
3741 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3742 /// currently selected permutation
3743 r_cg_permutation_t *r_cg_permutation;
3744 /// storage for permutations linked in the hash table
3745 memexpandablearray_t r_cg_permutationarray;
3747 #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));}}
3749 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3751 //unsigned int hashdepth = 0;
3752 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3753 r_cg_permutation_t *p;
3754 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3756 if (p->mode == mode && p->permutation == permutation)
3758 //if (hashdepth > 10)
3759 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3764 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3766 p->permutation = permutation;
3767 p->hashnext = r_cg_permutationhash[mode][hashindex];
3768 r_cg_permutationhash[mode][hashindex] = p;
3769 //if (hashdepth > 10)
3770 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3774 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3777 if (!filename || !filename[0])
3779 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3782 if (printfromdisknotice)
3783 Con_DPrintf("from disk %s... ", filename);
3784 return shaderstring;
3786 else if (!strcmp(filename, "cg/default.cg"))
3788 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3789 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3791 return shaderstring;
3794 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3797 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3798 int vertstrings_count = 0, vertstring_length = 0;
3799 int geomstrings_count = 0, geomstring_length = 0;
3800 int fragstrings_count = 0, fragstring_length = 0;
3802 char *vertexstring, *geometrystring, *fragmentstring;
3803 char *vertstring, *geomstring, *fragstring;
3804 const char *vertstrings_list[32+3];
3805 const char *geomstrings_list[32+3];
3806 const char *fragstrings_list[32+3];
3807 char permutationname[256];
3808 CGprofile vertexProfile;
3809 CGprofile fragmentProfile;
3817 permutationname[0] = 0;
3818 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
3819 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3820 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3822 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3824 // the first pretext is which type of shader to compile as
3825 // (later these will all be bound together as a program object)
3826 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3827 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3828 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3830 // the second pretext is the mode (for example a light source)
3831 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3832 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3833 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3834 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3836 // now add all the permutation pretexts
3837 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3839 if (permutation & (1<<i))
3841 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3842 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3843 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3844 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3848 // keep line numbers correct
3849 vertstrings_list[vertstrings_count++] = "\n";
3850 geomstrings_list[geomstrings_count++] = "\n";
3851 fragstrings_list[fragstrings_count++] = "\n";
3855 // now append the shader text itself
3856 vertstrings_list[vertstrings_count++] = vertexstring;
3857 geomstrings_list[geomstrings_count++] = geometrystring;
3858 fragstrings_list[fragstrings_count++] = fragmentstring;
3860 // if any sources were NULL, clear the respective list
3862 vertstrings_count = 0;
3863 if (!geometrystring)
3864 geomstrings_count = 0;
3865 if (!fragmentstring)
3866 fragstrings_count = 0;
3868 vertstring_length = 0;
3869 for (i = 0;i < vertstrings_count;i++)
3870 vertstring_length += strlen(vertstrings_list[i]);
3871 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3872 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3873 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3875 geomstring_length = 0;
3876 for (i = 0;i < geomstrings_count;i++)
3877 geomstring_length += strlen(geomstrings_list[i]);
3878 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3879 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3880 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3882 fragstring_length = 0;
3883 for (i = 0;i < fragstrings_count;i++)
3884 fragstring_length += strlen(fragstrings_list[i]);
3885 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3886 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3887 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3891 //vertexProfile = CG_PROFILE_ARBVP1;
3892 //fragmentProfile = CG_PROFILE_ARBFP1;
3893 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3894 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3895 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3896 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3897 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3900 // compile the vertex program
3901 if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL)))
3904 cgCompileProgram(p->vprogram);CHECKCGERROR
3905 if (!cgIsProgramCompiled(p->vprogram))
3908 cgDestroyProgram(p->vprogram);CHECKCGERROR
3913 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3914 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3915 // look up all the uniform variable names we care about, so we don't
3916 // have to look them up every time we set them
3918 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
3919 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
3920 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
3921 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
3922 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
3923 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
3924 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3925 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3926 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3931 // compile the fragment program
3932 if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL)))
3934 cgCompileProgram(p->fprogram);CHECKCGERROR
3935 if (!cgIsProgramCompiled(p->fprogram))
3938 cgDestroyProgram(p->fprogram);CHECKCGERROR
3943 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3944 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3946 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
3947 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
3948 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3949 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3950 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
3951 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3952 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3953 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3954 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3955 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3956 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3957 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3958 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3959 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3960 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3961 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3962 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3963 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3964 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3965 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3966 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3967 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3968 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3969 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3970 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3971 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3972 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3973 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3974 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
3975 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3976 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
3977 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
3978 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
3979 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
3980 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
3981 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
3982 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
3983 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
3984 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
3985 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
3986 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
3987 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
3988 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
3989 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
3990 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
3991 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
3992 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
3993 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
3994 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
3995 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
3996 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
3997 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
3998 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
3999 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4000 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4001 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4002 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4003 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4004 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4005 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4006 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4007 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4008 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4009 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4010 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4011 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4012 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4013 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4014 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4015 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4016 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4021 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4022 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4024 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4028 Mem_Free(vertstring);
4030 Mem_Free(geomstring);
4032 Mem_Free(fragstring);
4034 Mem_Free(vertexstring);
4036 Mem_Free(geometrystring);
4038 Mem_Free(fragmentstring);
4041 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4043 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4046 if (r_cg_permutation != perm)
4048 r_cg_permutation = perm;
4049 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4051 if (!r_cg_permutation->compiled)
4052 R_CG_CompilePermutation(perm, mode, permutation);
4053 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4055 // remove features until we find a valid permutation
4057 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4059 // reduce i more quickly whenever it would not remove any bits
4060 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4061 if (!(permutation & j))
4064 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4065 if (!r_cg_permutation->compiled)
4066 R_CG_CompilePermutation(perm, mode, permutation);
4067 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4070 if (i >= SHADERPERMUTATION_COUNT)
4072 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4073 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4074 return; // no bit left to clear, entire mode is broken
4080 if (r_cg_permutation->vprogram)
4082 //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4083 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4084 //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4088 //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4089 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4091 if (r_cg_permutation->fprogram)
4093 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4094 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4095 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4099 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4100 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4104 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4105 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4108 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4110 cgGLSetTextureParameter(param, R_GetTexture(tex));
4111 cgGLEnableTextureParameter(param);
4115 void R_GLSL_Restart_f(void)
4117 unsigned int i, limit;
4118 switch(vid.renderpath)
4120 case RENDERPATH_GL20:
4122 r_glsl_permutation_t *p;
4123 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4124 for (i = 0;i < limit;i++)
4126 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4128 GL_Backend_FreeProgram(p->program);
4129 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4132 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4135 case RENDERPATH_CGGL:
4138 r_cg_permutation_t *p;
4139 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4140 for (i = 0;i < limit;i++)
4142 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4145 cgDestroyProgram(p->vprogram);
4147 cgDestroyProgram(p->fprogram);
4148 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4152 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4155 case RENDERPATH_GL13:
4156 case RENDERPATH_GL11:
4161 void R_GLSL_DumpShader_f(void)
4166 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4169 FS_Print(file, "/* The engine may define the following macros:\n");
4170 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4171 for (i = 0;i < SHADERMODE_COUNT;i++)
4172 FS_Print(file, glslshadermodeinfo[i].pretext);
4173 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4174 FS_Print(file, shaderpermutationinfo[i].pretext);
4175 FS_Print(file, "*/\n");
4176 FS_Print(file, builtinshaderstring);
4178 Con_Printf("glsl/default.glsl written\n");
4181 Con_Printf("failed to write to glsl/default.glsl\n");
4184 file = FS_OpenRealFile("cg/default.cg", "w", false);
4187 FS_Print(file, "/* The engine may define the following macros:\n");
4188 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4189 for (i = 0;i < SHADERMODE_COUNT;i++)
4190 FS_Print(file, cgshadermodeinfo[i].pretext);
4191 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4192 FS_Print(file, shaderpermutationinfo[i].pretext);
4193 FS_Print(file, "*/\n");
4194 FS_Print(file, builtincgshaderstring);
4196 Con_Printf("cg/default.cg written\n");
4199 Con_Printf("failed to write to cg/default.cg\n");
4203 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4206 texturemode = GL_MODULATE;
4207 switch (vid.renderpath)
4209 case RENDERPATH_GL20:
4210 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))));
4211 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4212 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4214 case RENDERPATH_CGGL:
4217 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))));
4218 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4219 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4222 case RENDERPATH_GL13:
4223 R_Mesh_TexBind(0, first );
4224 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4225 R_Mesh_TexBind(1, second);
4227 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4229 case RENDERPATH_GL11:
4230 R_Mesh_TexBind(0, first );
4235 void R_SetupShader_DepthOrShadow(void)
4237 switch (vid.renderpath)
4239 case RENDERPATH_GL20:
4240 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4242 case RENDERPATH_CGGL:
4244 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4247 case RENDERPATH_GL13:
4248 R_Mesh_TexBind(0, 0);
4249 R_Mesh_TexBind(1, 0);
4251 case RENDERPATH_GL11:
4252 R_Mesh_TexBind(0, 0);
4257 void R_SetupShader_ShowDepth(void)
4259 switch (vid.renderpath)
4261 case RENDERPATH_GL20:
4262 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4264 case RENDERPATH_CGGL:
4266 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4269 case RENDERPATH_GL13:
4271 case RENDERPATH_GL11:
4276 extern qboolean r_shadow_usingdeferredprepass;
4277 extern cvar_t r_shadow_deferred_8bitrange;
4278 extern rtexture_t *r_shadow_attenuationgradienttexture;
4279 extern rtexture_t *r_shadow_attenuation2dtexture;
4280 extern rtexture_t *r_shadow_attenuation3dtexture;
4281 extern qboolean r_shadow_usingshadowmaprect;
4282 extern qboolean r_shadow_usingshadowmapcube;
4283 extern qboolean r_shadow_usingshadowmap2d;
4284 extern float r_shadow_shadowmap_texturescale[2];
4285 extern float r_shadow_shadowmap_parameters[4];
4286 extern qboolean r_shadow_shadowmapvsdct;
4287 extern qboolean r_shadow_shadowmapsampler;
4288 extern int r_shadow_shadowmappcf;
4289 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4290 extern rtexture_t *r_shadow_shadowmap2dtexture;
4291 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4292 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4293 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4294 extern int r_shadow_prepass_width;
4295 extern int r_shadow_prepass_height;
4296 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4297 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4298 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4299 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4300 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4302 // select a permutation of the lighting shader appropriate to this
4303 // combination of texture, entity, light source, and fogging, only use the
4304 // minimum features necessary to avoid wasting rendering time in the
4305 // fragment shader on features that are not being used
4306 unsigned int permutation = 0;
4307 unsigned int mode = 0;
4309 // TODO: implement geometry-shader based shadow volumes someday
4310 if (r_glsl_offsetmapping.integer)
4312 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4313 if (r_glsl_offsetmapping_reliefmapping.integer)
4314 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4316 if (rsurfacepass == RSURFPASS_BACKGROUND)
4318 // distorted background
4319 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4320 mode = SHADERMODE_WATER;
4322 mode = SHADERMODE_REFRACTION;
4324 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4326 // normalmap (deferred prepass), may use alpha test on diffuse
4327 mode = SHADERMODE_DEFERREDGEOMETRY;
4328 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4329 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4330 if (r_glsl_offsetmapping.integer)
4332 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4333 if (r_glsl_offsetmapping_reliefmapping.integer)
4334 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4337 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4340 mode = SHADERMODE_LIGHTSOURCE;
4341 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4342 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4343 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4344 permutation |= SHADERPERMUTATION_CUBEFILTER;
4345 if (diffusescale > 0)
4346 permutation |= SHADERPERMUTATION_DIFFUSE;
4347 if (specularscale > 0)
4348 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4349 if (r_refdef.fogenabled)
4350 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4351 if (rsurface.texture->colormapping)
4352 permutation |= SHADERPERMUTATION_COLORMAPPING;
4353 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4355 if (r_shadow_usingshadowmaprect)
4356 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4357 if (r_shadow_usingshadowmap2d)
4358 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4359 if (r_shadow_usingshadowmapcube)
4360 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4361 else if(r_shadow_shadowmapvsdct)
4362 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4364 if (r_shadow_shadowmapsampler)
4365 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4366 if (r_shadow_shadowmappcf > 1)
4367 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4368 else if (r_shadow_shadowmappcf)
4369 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4372 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4374 // unshaded geometry (fullbright or ambient model lighting)
4375 mode = SHADERMODE_FLATCOLOR;
4376 ambientscale = diffusescale = specularscale = 0;
4377 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4378 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4379 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4380 permutation |= SHADERPERMUTATION_GLOW;
4381 if (r_refdef.fogenabled)
4382 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4383 if (rsurface.texture->colormapping)
4384 permutation |= SHADERPERMUTATION_COLORMAPPING;
4385 if (r_glsl_offsetmapping.integer)
4387 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4388 if (r_glsl_offsetmapping_reliefmapping.integer)
4389 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4391 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4392 permutation |= SHADERPERMUTATION_REFLECTION;
4394 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4396 // directional model lighting
4397 mode = SHADERMODE_LIGHTDIRECTION;
4398 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4399 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4400 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4401 permutation |= SHADERPERMUTATION_GLOW;
4402 permutation |= SHADERPERMUTATION_DIFFUSE;
4403 if (specularscale > 0)
4404 permutation |= SHADERPERMUTATION_SPECULAR;
4405 if (r_refdef.fogenabled)
4406 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4407 if (rsurface.texture->colormapping)
4408 permutation |= SHADERPERMUTATION_COLORMAPPING;
4409 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4410 permutation |= SHADERPERMUTATION_REFLECTION;
4411 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4412 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4414 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4416 // ambient model lighting
4417 mode = SHADERMODE_LIGHTDIRECTION;
4418 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4419 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4420 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4421 permutation |= SHADERPERMUTATION_GLOW;
4422 if (r_refdef.fogenabled)
4423 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4424 if (rsurface.texture->colormapping)
4425 permutation |= SHADERPERMUTATION_COLORMAPPING;
4426 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4427 permutation |= SHADERPERMUTATION_REFLECTION;
4428 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4429 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4434 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4436 // deluxemapping (light direction texture)
4437 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4438 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4440 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4441 permutation |= SHADERPERMUTATION_DIFFUSE;
4442 if (specularscale > 0)
4443 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4445 else if (r_glsl_deluxemapping.integer >= 2)
4447 // fake deluxemapping (uniform light direction in tangentspace)
4448 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4449 permutation |= SHADERPERMUTATION_DIFFUSE;
4450 if (specularscale > 0)
4451 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4453 else if (rsurface.uselightmaptexture)
4455 // ordinary lightmapping (q1bsp, q3bsp)
4456 mode = SHADERMODE_LIGHTMAP;
4460 // ordinary vertex coloring (q3bsp)
4461 mode = SHADERMODE_VERTEXCOLOR;
4463 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4464 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4465 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4466 permutation |= SHADERPERMUTATION_GLOW;
4467 if (r_refdef.fogenabled)
4468 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4469 if (rsurface.texture->colormapping)
4470 permutation |= SHADERPERMUTATION_COLORMAPPING;
4471 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4472 permutation |= SHADERPERMUTATION_REFLECTION;
4473 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4474 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4476 if(permutation & SHADERPERMUTATION_SPECULAR)
4477 if(r_shadow_glossexact.integer)
4478 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4479 if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
4480 permutation |= SHADERPERMUTATION_ALPHAKILL;
4481 switch(vid.renderpath)
4483 case RENDERPATH_GL20:
4484 R_SetupShader_SetPermutationGLSL(mode, permutation);
4485 if (mode == SHADERMODE_LIGHTSOURCE)
4487 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4488 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4489 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4490 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);
4491 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);
4492 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
4494 // additive passes are only darkened by fog, not tinted
4495 if (r_glsl_permutation->loc_FogColor >= 0)
4496 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4497 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]);
4498 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]);
4499 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4503 if (mode == SHADERMODE_FLATCOLOR)
4505 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4507 else if (mode == SHADERMODE_LIGHTDIRECTION)
4509 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]);
4510 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);
4511 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4512 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);
4513 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
4514 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]);
4515 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]);
4519 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]);
4520 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]);
4521 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4522 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);
4523 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);
4525 // additive passes are only darkened by fog, not tinted
4526 if (r_glsl_permutation->loc_FogColor >= 0)
4528 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4529 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4531 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4533 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);
4534 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]);
4535 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]);
4536 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4537 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4538 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4539 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4540 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4542 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4543 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4544 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4545 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4546 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4547 if (r_glsl_permutation->loc_Color_Pants >= 0)
4549 if (rsurface.texture->pantstexture)
4550 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4552 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4554 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4556 if (rsurface.texture->shirttexture)
4557 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4559 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4561 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]);
4562 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4563 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4564 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4565 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4566 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]);
4568 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
4569 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
4570 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
4571 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
4572 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
4573 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
4574 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
4575 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
4576 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
4577 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
4578 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
4579 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
4580 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
4581 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
4582 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white );
4583 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_blanknormalmap );
4584 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
4585 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , r_texture_white );
4586 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , r_texture_white );
4587 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
4588 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
4589 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
4590 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
4591 if (rsurface.rtlight)
4593 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
4594 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
4595 if (r_shadow_usingshadowmapcube)
4596 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4597 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
4598 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
4602 case RENDERPATH_CGGL:
4604 R_SetupShader_SetPermutationCG(mode, permutation);
4605 if (mode == SHADERMODE_LIGHTSOURCE)
4607 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4608 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4612 if (mode == SHADERMODE_LIGHTDIRECTION)
4614 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
4617 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4618 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4619 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4620 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
4623 if (mode == SHADERMODE_LIGHTSOURCE)
4625 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4626 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4627 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
4628 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
4629 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
4631 // additive passes are only darkened by fog, not tinted
4632 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4633 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
4634 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
4635 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4639 if (mode == SHADERMODE_FLATCOLOR)
4641 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4643 else if (mode == SHADERMODE_LIGHTDIRECTION)
4645 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
4646 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);CHECKCGERROR
4647 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
4648 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
4649 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
4650 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
4651 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
4655 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
4656 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
4657 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
4658 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
4659 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
4661 // additive passes are only darkened by fog, not tinted
4662 if (r_cg_permutation->fp_FogColor)
4664 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4665 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4667 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4670 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
4671 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
4672 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
4673 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4674 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4675 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4676 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4677 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4679 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4680 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4681 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4682 if (r_cg_permutation->fp_Color_Pants)
4684 if (rsurface.texture->pantstexture)
4685 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4687 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4690 if (r_cg_permutation->fp_Color_Shirt)
4692 if (rsurface.texture->shirttexture)
4693 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4695 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4698 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
4699 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4700 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4701 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4702 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4703 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
4705 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
4706 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
4707 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
4708 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
4709 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
4710 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
4711 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
4712 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
4713 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
4714 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
4715 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
4716 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
4717 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
4718 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
4719 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , r_texture_white );CHECKCGERROR
4720 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , r_texture_blanknormalmap );CHECKCGERROR
4721 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
4722 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , r_texture_white );CHECKCGERROR
4723 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , r_texture_white );CHECKCGERROR
4724 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
4725 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
4726 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
4727 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
4728 if (rsurface.rtlight)
4730 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
4731 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
4732 if (r_shadow_usingshadowmapcube)
4733 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4734 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
4735 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
4741 case RENDERPATH_GL13:
4742 case RENDERPATH_GL11:
4747 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4749 // select a permutation of the lighting shader appropriate to this
4750 // combination of texture, entity, light source, and fogging, only use the
4751 // minimum features necessary to avoid wasting rendering time in the
4752 // fragment shader on features that are not being used
4753 unsigned int permutation = 0;
4754 unsigned int mode = 0;
4755 const float *lightcolorbase = rtlight->currentcolor;
4756 float ambientscale = rtlight->ambientscale;
4757 float diffusescale = rtlight->diffusescale;
4758 float specularscale = rtlight->specularscale;
4759 // this is the location of the light in view space
4760 vec3_t viewlightorigin;
4761 // this transforms from view space (camera) to light space (cubemap)
4762 matrix4x4_t viewtolight;
4763 matrix4x4_t lighttoview;
4764 float viewtolight16f[16];
4765 float range = 1.0f / r_shadow_deferred_8bitrange.value;
4767 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4768 if (rtlight->currentcubemap != r_texture_whitecube)
4769 permutation |= SHADERPERMUTATION_CUBEFILTER;
4770 if (diffusescale > 0)
4771 permutation |= SHADERPERMUTATION_DIFFUSE;
4772 if (specularscale > 0)
4774 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4775 if (r_shadow_glossexact.integer)
4776 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4778 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4780 if (r_shadow_usingshadowmaprect)
4781 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4782 if (r_shadow_usingshadowmap2d)
4783 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4784 if (r_shadow_usingshadowmapcube)
4785 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4786 else if(r_shadow_shadowmapvsdct)
4787 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4789 if (r_shadow_shadowmapsampler)
4790 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4791 if (r_shadow_shadowmappcf > 1)
4792 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4793 else if (r_shadow_shadowmappcf)
4794 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4796 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4797 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4798 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4799 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4800 switch(vid.renderpath)
4802 case RENDERPATH_GL20:
4803 R_SetupShader_SetPermutationGLSL(mode, permutation);
4804 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4805 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
4806 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);
4807 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);
4808 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);
4809 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]);
4810 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]);
4811 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));
4812 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]);
4814 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
4815 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
4816 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
4817 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
4818 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
4819 if (r_shadow_usingshadowmapcube)
4820 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4821 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
4822 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
4824 case RENDERPATH_CGGL:
4826 R_SetupShader_SetPermutationCG(mode, permutation);
4827 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4828 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4829 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
4830 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
4831 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
4832 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
4833 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
4834 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
4835 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
4837 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
4838 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
4839 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
4840 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
4841 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
4842 if (r_shadow_usingshadowmapcube)
4843 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4844 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
4845 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
4848 case RENDERPATH_GL13:
4849 case RENDERPATH_GL11:
4854 #define SKINFRAME_HASH 1024
4858 int loadsequence; // incremented each level change
4859 memexpandablearray_t array;
4860 skinframe_t *hash[SKINFRAME_HASH];
4863 r_skinframe_t r_skinframe;
4865 void R_SkinFrame_PrepareForPurge(void)
4867 r_skinframe.loadsequence++;
4868 // wrap it without hitting zero
4869 if (r_skinframe.loadsequence >= 200)
4870 r_skinframe.loadsequence = 1;
4873 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
4877 // mark the skinframe as used for the purging code
4878 skinframe->loadsequence = r_skinframe.loadsequence;
4881 void R_SkinFrame_Purge(void)
4885 for (i = 0;i < SKINFRAME_HASH;i++)
4887 for (s = r_skinframe.hash[i];s;s = s->next)
4889 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
4891 if (s->merged == s->base)
4893 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
4894 R_PurgeTexture(s->stain );s->stain = NULL;
4895 R_PurgeTexture(s->merged);s->merged = NULL;
4896 R_PurgeTexture(s->base );s->base = NULL;
4897 R_PurgeTexture(s->pants );s->pants = NULL;
4898 R_PurgeTexture(s->shirt );s->shirt = NULL;
4899 R_PurgeTexture(s->nmap );s->nmap = NULL;
4900 R_PurgeTexture(s->gloss );s->gloss = NULL;
4901 R_PurgeTexture(s->glow );s->glow = NULL;
4902 R_PurgeTexture(s->fog );s->fog = NULL;
4903 s->loadsequence = 0;
4909 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
4911 char basename[MAX_QPATH];
4913 Image_StripImageExtension(name, basename, sizeof(basename));
4915 if( last == NULL ) {
4917 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4918 item = r_skinframe.hash[hashindex];
4923 // linearly search through the hash bucket
4924 for( ; item ; item = item->next ) {
4925 if( !strcmp( item->basename, basename ) ) {
4932 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
4936 char basename[MAX_QPATH];
4938 Image_StripImageExtension(name, basename, sizeof(basename));
4940 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4941 for (item = r_skinframe.hash[hashindex];item;item = item->next)
4942 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
4946 rtexture_t *dyntexture;
4947 // check whether its a dynamic texture
4948 dyntexture = CL_GetDynTexture( basename );
4949 if (!add && !dyntexture)
4951 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
4952 memset(item, 0, sizeof(*item));
4953 strlcpy(item->basename, basename, sizeof(item->basename));
4954 item->base = dyntexture; // either NULL or dyntexture handle
4955 item->textureflags = textureflags;
4956 item->comparewidth = comparewidth;
4957 item->compareheight = compareheight;
4958 item->comparecrc = comparecrc;
4959 item->next = r_skinframe.hash[hashindex];
4960 r_skinframe.hash[hashindex] = item;
4962 else if( item->base == NULL )
4964 rtexture_t *dyntexture;
4965 // check whether its a dynamic texture
4966 // 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]
4967 dyntexture = CL_GetDynTexture( basename );
4968 item->base = dyntexture; // either NULL or dyntexture handle
4971 R_SkinFrame_MarkUsed(item);
4975 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
4977 unsigned long long avgcolor[5], wsum; \
4985 for(pix = 0; pix < cnt; ++pix) \
4988 for(comp = 0; comp < 3; ++comp) \
4990 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
4993 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4995 for(comp = 0; comp < 3; ++comp) \
4996 avgcolor[comp] += getpixel * w; \
4999 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5000 avgcolor[4] += getpixel; \
5002 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5004 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5005 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5006 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5007 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5010 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5013 unsigned char *pixels;
5014 unsigned char *bumppixels;
5015 unsigned char *basepixels = NULL;
5016 int basepixels_width = 0;
5017 int basepixels_height = 0;
5018 skinframe_t *skinframe;
5019 rtexture_t *ddsbase = NULL;
5020 qboolean ddshasalpha = false;
5021 float ddsavgcolor[4];
5022 char basename[MAX_QPATH];
5024 if (cls.state == ca_dedicated)
5027 // return an existing skinframe if already loaded
5028 // if loading of the first image fails, don't make a new skinframe as it
5029 // would cause all future lookups of this to be missing
5030 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5031 if (skinframe && skinframe->base)
5034 Image_StripImageExtension(name, basename, sizeof(basename));
5036 // check for DDS texture file first
5037 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5039 basepixels = loadimagepixelsbgra(name, complain, true);
5040 if (basepixels == NULL)
5044 if (developer_loading.integer)
5045 Con_Printf("loading skin \"%s\"\n", name);
5047 // we've got some pixels to store, so really allocate this new texture now
5049 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5050 skinframe->stain = NULL;
5051 skinframe->merged = NULL;
5052 skinframe->base = NULL;
5053 skinframe->pants = NULL;
5054 skinframe->shirt = NULL;
5055 skinframe->nmap = NULL;
5056 skinframe->gloss = NULL;
5057 skinframe->glow = NULL;
5058 skinframe->fog = NULL;
5059 skinframe->hasalpha = false;
5063 skinframe->base = ddsbase;
5064 skinframe->hasalpha = ddshasalpha;
5065 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5066 if (r_loadfog && skinframe->hasalpha)
5067 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5068 //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]);
5072 basepixels_width = image_width;
5073 basepixels_height = image_height;
5074 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);
5075 if (textureflags & TEXF_ALPHA)
5077 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5079 if (basepixels[j] < 255)
5081 skinframe->hasalpha = true;
5085 if (r_loadfog && skinframe->hasalpha)
5087 // has transparent pixels
5088 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5089 for (j = 0;j < image_width * image_height * 4;j += 4)
5094 pixels[j+3] = basepixels[j+3];
5096 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);
5100 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5101 //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]);
5102 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5103 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5104 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5105 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5110 if (r_loadnormalmap)
5111 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5112 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5114 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5115 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5116 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5119 // _norm is the name used by tenebrae and has been adopted as standard
5120 if (r_loadnormalmap && skinframe->nmap == NULL)
5122 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5124 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);
5128 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5130 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5131 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5132 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);
5134 Mem_Free(bumppixels);
5136 else if (r_shadow_bumpscale_basetexture.value > 0)
5138 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5139 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5140 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);
5143 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5144 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5147 // _luma is supported only for tenebrae compatibility
5148 // _glow is the preferred name
5149 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5151 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);
5152 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5153 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5154 Mem_Free(pixels);pixels = NULL;
5157 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5159 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);
5160 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5161 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5166 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5168 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);
5169 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5170 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5175 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5177 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);
5178 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5179 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5185 Mem_Free(basepixels);
5190 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5191 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5194 unsigned char *temp1, *temp2;
5195 skinframe_t *skinframe;
5197 if (cls.state == ca_dedicated)
5200 // if already loaded just return it, otherwise make a new skinframe
5201 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5202 if (skinframe && skinframe->base)
5205 skinframe->stain = NULL;
5206 skinframe->merged = NULL;
5207 skinframe->base = NULL;
5208 skinframe->pants = NULL;
5209 skinframe->shirt = NULL;
5210 skinframe->nmap = NULL;
5211 skinframe->gloss = NULL;
5212 skinframe->glow = NULL;
5213 skinframe->fog = NULL;
5214 skinframe->hasalpha = false;
5216 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5220 if (developer_loading.integer)
5221 Con_Printf("loading 32bit skin \"%s\"\n", name);
5223 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5225 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5226 temp2 = temp1 + width * height * 4;
5227 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5228 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5231 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5232 if (textureflags & TEXF_ALPHA)
5234 for (i = 3;i < width * height * 4;i += 4)
5236 if (skindata[i] < 255)
5238 skinframe->hasalpha = true;
5242 if (r_loadfog && skinframe->hasalpha)
5244 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5245 memcpy(fogpixels, skindata, width * height * 4);
5246 for (i = 0;i < width * height * 4;i += 4)
5247 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5248 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5249 Mem_Free(fogpixels);
5253 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5254 //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]);
5259 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5263 skinframe_t *skinframe;
5265 if (cls.state == ca_dedicated)
5268 // if already loaded just return it, otherwise make a new skinframe
5269 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5270 if (skinframe && skinframe->base)
5273 skinframe->stain = NULL;
5274 skinframe->merged = NULL;
5275 skinframe->base = NULL;
5276 skinframe->pants = NULL;
5277 skinframe->shirt = NULL;
5278 skinframe->nmap = NULL;
5279 skinframe->gloss = NULL;
5280 skinframe->glow = NULL;
5281 skinframe->fog = NULL;
5282 skinframe->hasalpha = false;
5284 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5288 if (developer_loading.integer)
5289 Con_Printf("loading quake skin \"%s\"\n", name);
5291 // 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)
5292 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5293 memcpy(skinframe->qpixels, skindata, width*height);
5294 skinframe->qwidth = width;
5295 skinframe->qheight = height;
5298 for (i = 0;i < width * height;i++)
5299 featuresmask |= palette_featureflags[skindata[i]];
5301 skinframe->hasalpha = false;
5302 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5303 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5304 skinframe->qgeneratemerged = true;
5305 skinframe->qgeneratebase = skinframe->qhascolormapping;
5306 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5308 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5309 //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]);
5314 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5318 unsigned char *skindata;
5320 if (!skinframe->qpixels)
5323 if (!skinframe->qhascolormapping)
5324 colormapped = false;
5328 if (!skinframe->qgeneratebase)
5333 if (!skinframe->qgeneratemerged)
5337 width = skinframe->qwidth;
5338 height = skinframe->qheight;
5339 skindata = skinframe->qpixels;
5341 if (skinframe->qgeneratenmap)
5343 unsigned char *temp1, *temp2;
5344 skinframe->qgeneratenmap = false;
5345 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5346 temp2 = temp1 + width * height * 4;
5347 // use either a custom palette or the quake palette
5348 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5349 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5350 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5354 if (skinframe->qgenerateglow)
5356 skinframe->qgenerateglow = false;
5357 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5362 skinframe->qgeneratebase = false;
5363 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);
5364 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5365 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5369 skinframe->qgeneratemerged = false;
5370 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5373 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5375 Mem_Free(skinframe->qpixels);
5376 skinframe->qpixels = NULL;
5380 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)
5383 skinframe_t *skinframe;
5385 if (cls.state == ca_dedicated)
5388 // if already loaded just return it, otherwise make a new skinframe
5389 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5390 if (skinframe && skinframe->base)
5393 skinframe->stain = NULL;
5394 skinframe->merged = NULL;
5395 skinframe->base = NULL;
5396 skinframe->pants = NULL;
5397 skinframe->shirt = NULL;
5398 skinframe->nmap = NULL;
5399 skinframe->gloss = NULL;
5400 skinframe->glow = NULL;
5401 skinframe->fog = NULL;
5402 skinframe->hasalpha = false;
5404 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5408 if (developer_loading.integer)
5409 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5411 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5412 if (textureflags & TEXF_ALPHA)
5414 for (i = 0;i < width * height;i++)
5416 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5418 skinframe->hasalpha = true;
5422 if (r_loadfog && skinframe->hasalpha)
5423 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5426 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5427 //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]);
5432 skinframe_t *R_SkinFrame_LoadMissing(void)
5434 skinframe_t *skinframe;
5436 if (cls.state == ca_dedicated)
5439 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5440 skinframe->stain = NULL;
5441 skinframe->merged = NULL;
5442 skinframe->base = NULL;
5443 skinframe->pants = NULL;
5444 skinframe->shirt = NULL;
5445 skinframe->nmap = NULL;
5446 skinframe->gloss = NULL;
5447 skinframe->glow = NULL;
5448 skinframe->fog = NULL;
5449 skinframe->hasalpha = false;
5451 skinframe->avgcolor[0] = rand() / RAND_MAX;
5452 skinframe->avgcolor[1] = rand() / RAND_MAX;
5453 skinframe->avgcolor[2] = rand() / RAND_MAX;
5454 skinframe->avgcolor[3] = 1;
5459 void R_Main_FreeViewCache(void)
5461 if (r_refdef.viewcache.entityvisible)
5462 Mem_Free(r_refdef.viewcache.entityvisible);
5463 if (r_refdef.viewcache.world_pvsbits)
5464 Mem_Free(r_refdef.viewcache.world_pvsbits);
5465 if (r_refdef.viewcache.world_leafvisible)
5466 Mem_Free(r_refdef.viewcache.world_leafvisible);
5467 if (r_refdef.viewcache.world_surfacevisible)
5468 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5469 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5472 void R_Main_ResizeViewCache(void)
5474 int numentities = r_refdef.scene.numentities;
5475 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5476 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5477 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5478 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5479 if (r_refdef.viewcache.maxentities < numentities)
5481 r_refdef.viewcache.maxentities = numentities;
5482 if (r_refdef.viewcache.entityvisible)
5483 Mem_Free(r_refdef.viewcache.entityvisible);
5484 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5486 if (r_refdef.viewcache.world_numclusters != numclusters)
5488 r_refdef.viewcache.world_numclusters = numclusters;
5489 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5490 if (r_refdef.viewcache.world_pvsbits)
5491 Mem_Free(r_refdef.viewcache.world_pvsbits);
5492 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5494 if (r_refdef.viewcache.world_numleafs != numleafs)
5496 r_refdef.viewcache.world_numleafs = numleafs;
5497 if (r_refdef.viewcache.world_leafvisible)
5498 Mem_Free(r_refdef.viewcache.world_leafvisible);
5499 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5501 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5503 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5504 if (r_refdef.viewcache.world_surfacevisible)
5505 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5506 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5510 extern rtexture_t *loadingscreentexture;
5511 void gl_main_start(void)
5513 loadingscreentexture = NULL;
5514 r_texture_blanknormalmap = NULL;
5515 r_texture_white = NULL;
5516 r_texture_grey128 = NULL;
5517 r_texture_black = NULL;
5518 r_texture_whitecube = NULL;
5519 r_texture_normalizationcube = NULL;
5520 r_texture_fogattenuation = NULL;
5521 r_texture_gammaramps = NULL;
5523 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5524 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5526 switch(vid.renderpath)
5528 case RENDERPATH_GL20:
5529 case RENDERPATH_CGGL:
5530 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5531 Cvar_SetValueQuick(&gl_combine, 1);
5532 Cvar_SetValueQuick(&r_glsl, 1);
5533 r_loadnormalmap = true;
5537 case RENDERPATH_GL13:
5538 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5539 Cvar_SetValueQuick(&gl_combine, 1);
5540 Cvar_SetValueQuick(&r_glsl, 0);
5541 r_loadnormalmap = false;
5542 r_loadgloss = false;
5545 case RENDERPATH_GL11:
5546 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5547 Cvar_SetValueQuick(&gl_combine, 0);
5548 Cvar_SetValueQuick(&r_glsl, 0);
5549 r_loadnormalmap = false;
5550 r_loadgloss = false;
5556 R_FrameData_Reset();
5560 memset(r_queries, 0, sizeof(r_queries));
5562 r_qwskincache = NULL;
5563 r_qwskincache_size = 0;
5565 // set up r_skinframe loading system for textures
5566 memset(&r_skinframe, 0, sizeof(r_skinframe));
5567 r_skinframe.loadsequence = 1;
5568 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5570 r_main_texturepool = R_AllocTexturePool();
5571 R_BuildBlankTextures();
5573 if (vid.support.arb_texture_cube_map)
5576 R_BuildNormalizationCube();
5578 r_texture_fogattenuation = NULL;
5579 r_texture_gammaramps = NULL;
5580 //r_texture_fogintensity = NULL;
5581 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5582 memset(&r_waterstate, 0, sizeof(r_waterstate));
5583 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5584 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5586 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5587 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5589 memset(&r_svbsp, 0, sizeof (r_svbsp));
5591 r_refdef.fogmasktable_density = 0;
5594 void gl_main_shutdown(void)
5597 R_FrameData_Reset();
5599 R_Main_FreeViewCache();
5602 qglDeleteQueriesARB(r_maxqueries, r_queries);
5606 memset(r_queries, 0, sizeof(r_queries));
5608 r_qwskincache = NULL;
5609 r_qwskincache_size = 0;
5611 // clear out the r_skinframe state
5612 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5613 memset(&r_skinframe, 0, sizeof(r_skinframe));
5616 Mem_Free(r_svbsp.nodes);
5617 memset(&r_svbsp, 0, sizeof (r_svbsp));
5618 R_FreeTexturePool(&r_main_texturepool);
5619 loadingscreentexture = NULL;
5620 r_texture_blanknormalmap = NULL;
5621 r_texture_white = NULL;
5622 r_texture_grey128 = NULL;
5623 r_texture_black = NULL;
5624 r_texture_whitecube = NULL;
5625 r_texture_normalizationcube = NULL;
5626 r_texture_fogattenuation = NULL;
5627 r_texture_gammaramps = NULL;
5628 //r_texture_fogintensity = NULL;
5629 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5630 memset(&r_waterstate, 0, sizeof(r_waterstate));
5634 extern void CL_ParseEntityLump(char *entitystring);
5635 void gl_main_newmap(void)
5637 // FIXME: move this code to client
5639 char *entities, entname[MAX_QPATH];
5641 Mem_Free(r_qwskincache);
5642 r_qwskincache = NULL;
5643 r_qwskincache_size = 0;
5646 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5647 l = (int)strlen(entname) - 4;
5648 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5650 memcpy(entname + l, ".ent", 5);
5651 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5653 CL_ParseEntityLump(entities);
5658 if (cl.worldmodel->brush.entities)
5659 CL_ParseEntityLump(cl.worldmodel->brush.entities);
5661 R_Main_FreeViewCache();
5663 R_FrameData_Reset();
5666 void GL_Main_Init(void)
5668 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5670 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5671 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5672 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5673 if (gamemode == GAME_NEHAHRA)
5675 Cvar_RegisterVariable (&gl_fogenable);
5676 Cvar_RegisterVariable (&gl_fogdensity);
5677 Cvar_RegisterVariable (&gl_fogred);
5678 Cvar_RegisterVariable (&gl_foggreen);
5679 Cvar_RegisterVariable (&gl_fogblue);
5680 Cvar_RegisterVariable (&gl_fogstart);
5681 Cvar_RegisterVariable (&gl_fogend);
5682 Cvar_RegisterVariable (&gl_skyclip);
5684 Cvar_RegisterVariable(&r_motionblur);
5685 Cvar_RegisterVariable(&r_motionblur_maxblur);
5686 Cvar_RegisterVariable(&r_motionblur_bmin);
5687 Cvar_RegisterVariable(&r_motionblur_vmin);
5688 Cvar_RegisterVariable(&r_motionblur_vmax);
5689 Cvar_RegisterVariable(&r_motionblur_vcoeff);
5690 Cvar_RegisterVariable(&r_motionblur_randomize);
5691 Cvar_RegisterVariable(&r_damageblur);
5692 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5693 Cvar_RegisterVariable(&r_equalize_entities_minambient);
5694 Cvar_RegisterVariable(&r_equalize_entities_by);
5695 Cvar_RegisterVariable(&r_equalize_entities_to);
5696 Cvar_RegisterVariable(&r_depthfirst);
5697 Cvar_RegisterVariable(&r_useinfinitefarclip);
5698 Cvar_RegisterVariable(&r_farclip_base);
5699 Cvar_RegisterVariable(&r_farclip_world);
5700 Cvar_RegisterVariable(&r_nearclip);
5701 Cvar_RegisterVariable(&r_showbboxes);
5702 Cvar_RegisterVariable(&r_showsurfaces);
5703 Cvar_RegisterVariable(&r_showtris);
5704 Cvar_RegisterVariable(&r_shownormals);
5705 Cvar_RegisterVariable(&r_showlighting);
5706 Cvar_RegisterVariable(&r_showshadowvolumes);
5707 Cvar_RegisterVariable(&r_showcollisionbrushes);
5708 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5709 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5710 Cvar_RegisterVariable(&r_showdisabledepthtest);
5711 Cvar_RegisterVariable(&r_drawportals);
5712 Cvar_RegisterVariable(&r_drawentities);
5713 Cvar_RegisterVariable(&r_cullentities_trace);
5714 Cvar_RegisterVariable(&r_cullentities_trace_samples);
5715 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5716 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5717 Cvar_RegisterVariable(&r_cullentities_trace_delay);
5718 Cvar_RegisterVariable(&r_drawviewmodel);
5719 Cvar_RegisterVariable(&r_speeds);
5720 Cvar_RegisterVariable(&r_fullbrights);
5721 Cvar_RegisterVariable(&r_wateralpha);
5722 Cvar_RegisterVariable(&r_dynamic);
5723 Cvar_RegisterVariable(&r_fullbright);
5724 Cvar_RegisterVariable(&r_shadows);
5725 Cvar_RegisterVariable(&r_shadows_darken);
5726 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5727 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5728 Cvar_RegisterVariable(&r_shadows_throwdistance);
5729 Cvar_RegisterVariable(&r_shadows_throwdirection);
5730 Cvar_RegisterVariable(&r_q1bsp_skymasking);
5731 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5732 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5733 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5734 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5735 Cvar_RegisterVariable(&r_fog_exp2);
5736 Cvar_RegisterVariable(&r_drawfog);
5737 Cvar_RegisterVariable(&r_transparentdepthmasking);
5738 Cvar_RegisterVariable(&r_texture_dds_load);
5739 Cvar_RegisterVariable(&r_texture_dds_save);
5740 Cvar_RegisterVariable(&r_textureunits);
5741 Cvar_RegisterVariable(&gl_combine);
5742 Cvar_RegisterVariable(&r_glsl);
5743 Cvar_RegisterVariable(&r_glsl_deluxemapping);
5744 Cvar_RegisterVariable(&r_glsl_offsetmapping);
5745 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5746 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5747 Cvar_RegisterVariable(&r_glsl_postprocess);
5748 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5749 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5750 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5751 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5752 Cvar_RegisterVariable(&r_water);
5753 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5754 Cvar_RegisterVariable(&r_water_clippingplanebias);
5755 Cvar_RegisterVariable(&r_water_refractdistort);
5756 Cvar_RegisterVariable(&r_water_reflectdistort);
5757 Cvar_RegisterVariable(&r_lerpsprites);
5758 Cvar_RegisterVariable(&r_lerpmodels);
5759 Cvar_RegisterVariable(&r_lerplightstyles);
5760 Cvar_RegisterVariable(&r_waterscroll);
5761 Cvar_RegisterVariable(&r_bloom);
5762 Cvar_RegisterVariable(&r_bloom_colorscale);
5763 Cvar_RegisterVariable(&r_bloom_brighten);
5764 Cvar_RegisterVariable(&r_bloom_blur);
5765 Cvar_RegisterVariable(&r_bloom_resolution);
5766 Cvar_RegisterVariable(&r_bloom_colorexponent);
5767 Cvar_RegisterVariable(&r_bloom_colorsubtract);
5768 Cvar_RegisterVariable(&r_hdr);
5769 Cvar_RegisterVariable(&r_hdr_scenebrightness);
5770 Cvar_RegisterVariable(&r_hdr_glowintensity);
5771 Cvar_RegisterVariable(&r_hdr_range);
5772 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5773 Cvar_RegisterVariable(&developer_texturelogging);
5774 Cvar_RegisterVariable(&gl_lightmaps);
5775 Cvar_RegisterVariable(&r_test);
5776 Cvar_RegisterVariable(&r_batchmode);
5777 Cvar_RegisterVariable(&r_glsl_saturation);
5778 Cvar_RegisterVariable(&r_framedatasize);
5779 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5780 Cvar_SetValue("r_fullbrights", 0);
5781 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5783 Cvar_RegisterVariable(&r_track_sprites);
5784 Cvar_RegisterVariable(&r_track_sprites_flags);
5785 Cvar_RegisterVariable(&r_track_sprites_scalew);
5786 Cvar_RegisterVariable(&r_track_sprites_scaleh);
5789 extern void R_Textures_Init(void);
5790 extern void GL_Draw_Init(void);
5791 extern void GL_Main_Init(void);
5792 extern void R_Shadow_Init(void);
5793 extern void R_Sky_Init(void);
5794 extern void GL_Surf_Init(void);
5795 extern void R_Particles_Init(void);
5796 extern void R_Explosion_Init(void);
5797 extern void gl_backend_init(void);
5798 extern void Sbar_Init(void);
5799 extern void R_LightningBeams_Init(void);
5800 extern void Mod_RenderInit(void);
5801 extern void Font_Init(void);
5803 void Render_Init(void)
5816 R_LightningBeams_Init();
5825 extern char *ENGINE_EXTENSIONS;
5828 gl_renderer = (const char *)qglGetString(GL_RENDERER);
5829 gl_vendor = (const char *)qglGetString(GL_VENDOR);
5830 gl_version = (const char *)qglGetString(GL_VERSION);
5831 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5835 if (!gl_platformextensions)
5836 gl_platformextensions = "";
5838 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5839 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5840 Con_Printf("GL_VERSION: %s\n", gl_version);
5841 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
5842 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
5844 VID_CheckExtensions();
5846 // LordHavoc: report supported extensions
5847 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
5849 // clear to black (loading plaque will be seen over this)
5851 qglClearColor(0,0,0,1);CHECKGLERROR
5852 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
5855 int R_CullBox(const vec3_t mins, const vec3_t maxs)
5859 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5861 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
5864 p = r_refdef.view.frustum + i;
5869 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5873 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5877 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5881 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5885 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5889 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5893 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5897 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5905 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
5909 for (i = 0;i < numplanes;i++)
5916 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5920 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5924 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5928 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5932 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5936 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5940 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5944 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5952 //==================================================================================
5954 // LordHavoc: this stores temporary data used within the same frame
5956 qboolean r_framedata_failed;
5957 static size_t r_framedata_size;
5958 static size_t r_framedata_current;
5959 static void *r_framedata_base;
5961 void R_FrameData_Reset(void)
5963 if (r_framedata_base)
5964 Mem_Free(r_framedata_base);
5965 r_framedata_base = NULL;
5966 r_framedata_size = 0;
5967 r_framedata_current = 0;
5968 r_framedata_failed = false;
5971 void R_FrameData_NewFrame(void)
5974 if (r_framedata_failed)
5975 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
5976 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
5977 wantedsize = bound(65536, wantedsize, 128*1024*1024);
5978 if (r_framedata_size != wantedsize)
5980 r_framedata_size = wantedsize;
5981 if (r_framedata_base)
5982 Mem_Free(r_framedata_base);
5983 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
5985 r_framedata_current = 0;
5986 r_framedata_failed = false;
5989 void *R_FrameData_Alloc(size_t size)
5993 // align to 16 byte boundary
5994 size = (size + 15) & ~15;
5995 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
5996 r_framedata_current += size;
5999 if (r_framedata_current > r_framedata_size)
6000 r_framedata_failed = true;
6002 // return NULL on everything after a failure
6003 if (r_framedata_failed)
6009 void *R_FrameData_Store(size_t size, void *data)
6011 void *d = R_FrameData_Alloc(size);
6013 memcpy(d, data, size);
6017 //==================================================================================
6019 // LordHavoc: animcache originally written by Echon, rewritten since then
6022 * Animation cache prevents re-generating mesh data for an animated model
6023 * multiple times in one frame for lighting, shadowing, reflections, etc.
6026 void R_AnimCache_Free(void)
6030 void R_AnimCache_ClearCache(void)
6033 entity_render_t *ent;
6035 for (i = 0;i < r_refdef.scene.numentities;i++)
6037 ent = r_refdef.scene.entities[i];
6038 ent->animcache_vertex3f = NULL;
6039 ent->animcache_normal3f = NULL;
6040 ent->animcache_svector3f = NULL;
6041 ent->animcache_tvector3f = NULL;
6045 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6047 dp_model_t *model = ent->model;
6049 // see if it's already cached this frame
6050 if (ent->animcache_vertex3f)
6052 // add normals/tangents if needed
6053 if (wantnormals || wanttangents)
6055 if (ent->animcache_normal3f)
6056 wantnormals = false;
6057 if (ent->animcache_svector3f)
6058 wanttangents = false;
6059 if (wantnormals || wanttangents)
6061 numvertices = model->surfmesh.num_vertices;
6063 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6066 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6067 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6069 if (!r_framedata_failed)
6070 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6076 // see if this ent is worth caching
6077 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6079 // get some memory for this entity and generate mesh data
6080 numvertices = model->surfmesh.num_vertices;
6081 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6083 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6086 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6087 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6089 if (!r_framedata_failed)
6090 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6092 return !r_framedata_failed;
6095 void R_AnimCache_CacheVisibleEntities(void)
6098 qboolean wantnormals = !r_showsurfaces.integer;
6099 qboolean wanttangents = !r_showsurfaces.integer;
6101 switch(vid.renderpath)
6103 case RENDERPATH_GL20:
6104 case RENDERPATH_CGGL:
6106 case RENDERPATH_GL13:
6107 case RENDERPATH_GL11:
6108 wanttangents = false;
6112 // TODO: thread this
6113 // NOTE: R_PrepareRTLights() also caches entities
6115 for (i = 0;i < r_refdef.scene.numentities;i++)
6116 if (r_refdef.viewcache.entityvisible[i])
6117 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6119 if (r_shadows.integer)
6120 for (i = 0;i < r_refdef.scene.numentities;i++)
6121 if (!r_refdef.viewcache.entityvisible[i])
6122 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6125 //==================================================================================
6127 static void R_View_UpdateEntityLighting (void)
6130 entity_render_t *ent;
6131 vec3_t tempdiffusenormal, avg;
6132 vec_t f, fa, fd, fdd;
6134 for (i = 0;i < r_refdef.scene.numentities;i++)
6136 ent = r_refdef.scene.entities[i];
6138 // skip unseen models
6139 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6143 if (ent->model && ent->model->brush.num_leafs)
6145 // TODO: use modellight for r_ambient settings on world?
6146 VectorSet(ent->modellight_ambient, 0, 0, 0);
6147 VectorSet(ent->modellight_diffuse, 0, 0, 0);
6148 VectorSet(ent->modellight_lightdir, 0, 0, 1);
6152 // fetch the lighting from the worldmodel data
6153 VectorClear(ent->modellight_ambient);
6154 VectorClear(ent->modellight_diffuse);
6155 VectorClear(tempdiffusenormal);
6156 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6159 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6160 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6161 if(ent->flags & RENDER_EQUALIZE)
6163 // first fix up ambient lighting...
6164 if(r_equalize_entities_minambient.value > 0)
6166 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6169 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6170 if(fa < r_equalize_entities_minambient.value * fd)
6173 // fa'/fd' = minambient
6174 // fa'+0.25*fd' = fa+0.25*fd
6176 // fa' = fd' * minambient
6177 // fd'*(0.25+minambient) = fa+0.25*fd
6179 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6180 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6182 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6183 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
6184 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6185 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6190 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6192 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6193 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6196 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6197 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6198 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6204 VectorSet(ent->modellight_ambient, 1, 1, 1);
6206 // move the light direction into modelspace coordinates for lighting code
6207 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6208 if(VectorLength2(ent->modellight_lightdir) == 0)
6209 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6210 VectorNormalize(ent->modellight_lightdir);
6214 #define MAX_LINEOFSIGHTTRACES 64
6216 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6219 vec3_t boxmins, boxmaxs;
6222 dp_model_t *model = r_refdef.scene.worldmodel;
6224 if (!model || !model->brush.TraceLineOfSight)
6227 // expand the box a little
6228 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6229 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6230 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6231 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6232 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6233 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6236 VectorCopy(eye, start);
6237 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6238 if (model->brush.TraceLineOfSight(model, start, end))
6241 // try various random positions
6242 for (i = 0;i < numsamples;i++)
6244 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6245 if (model->brush.TraceLineOfSight(model, start, end))
6253 static void R_View_UpdateEntityVisible (void)
6258 entity_render_t *ent;
6260 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6261 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6263 // worldmodel can check visibility
6264 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6265 for (i = 0;i < r_refdef.scene.numentities;i++)
6267 ent = r_refdef.scene.entities[i];
6268 if (!(ent->flags & renderimask))
6269 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)))
6270 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))
6271 r_refdef.viewcache.entityvisible[i] = true;
6273 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6275 for (i = 0;i < r_refdef.scene.numentities;i++)
6277 ent = r_refdef.scene.entities[i];
6278 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6280 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6282 continue; // temp entities do pvs only
6283 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6284 ent->last_trace_visibility = realtime;
6285 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6286 r_refdef.viewcache.entityvisible[i] = 0;
6293 // no worldmodel or it can't check visibility
6294 for (i = 0;i < r_refdef.scene.numentities;i++)
6296 ent = r_refdef.scene.entities[i];
6297 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));
6302 /// only used if skyrendermasked, and normally returns false
6303 int R_DrawBrushModelsSky (void)
6306 entity_render_t *ent;
6309 for (i = 0;i < r_refdef.scene.numentities;i++)
6311 if (!r_refdef.viewcache.entityvisible[i])
6313 ent = r_refdef.scene.entities[i];
6314 if (!ent->model || !ent->model->DrawSky)
6316 ent->model->DrawSky(ent);
6322 static void R_DrawNoModel(entity_render_t *ent);
6323 static void R_DrawModels(void)
6326 entity_render_t *ent;
6328 for (i = 0;i < r_refdef.scene.numentities;i++)
6330 if (!r_refdef.viewcache.entityvisible[i])
6332 ent = r_refdef.scene.entities[i];
6333 r_refdef.stats.entities++;
6334 if (ent->model && ent->model->Draw != NULL)
6335 ent->model->Draw(ent);
6341 static void R_DrawModelsDepth(void)
6344 entity_render_t *ent;
6346 for (i = 0;i < r_refdef.scene.numentities;i++)
6348 if (!r_refdef.viewcache.entityvisible[i])
6350 ent = r_refdef.scene.entities[i];
6351 if (ent->model && ent->model->DrawDepth != NULL)
6352 ent->model->DrawDepth(ent);
6356 static void R_DrawModelsDebug(void)
6359 entity_render_t *ent;
6361 for (i = 0;i < r_refdef.scene.numentities;i++)
6363 if (!r_refdef.viewcache.entityvisible[i])
6365 ent = r_refdef.scene.entities[i];
6366 if (ent->model && ent->model->DrawDebug != NULL)
6367 ent->model->DrawDebug(ent);
6371 static void R_DrawModelsAddWaterPlanes(void)
6374 entity_render_t *ent;
6376 for (i = 0;i < r_refdef.scene.numentities;i++)
6378 if (!r_refdef.viewcache.entityvisible[i])
6380 ent = r_refdef.scene.entities[i];
6381 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6382 ent->model->DrawAddWaterPlanes(ent);
6386 static void R_View_SetFrustum(void)
6389 double slopex, slopey;
6390 vec3_t forward, left, up, origin;
6392 // we can't trust r_refdef.view.forward and friends in reflected scenes
6393 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6396 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6397 r_refdef.view.frustum[0].normal[1] = 0 - 0;
6398 r_refdef.view.frustum[0].normal[2] = -1 - 0;
6399 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6400 r_refdef.view.frustum[1].normal[1] = 0 + 0;
6401 r_refdef.view.frustum[1].normal[2] = -1 + 0;
6402 r_refdef.view.frustum[2].normal[0] = 0 - 0;
6403 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6404 r_refdef.view.frustum[2].normal[2] = -1 - 0;
6405 r_refdef.view.frustum[3].normal[0] = 0 + 0;
6406 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6407 r_refdef.view.frustum[3].normal[2] = -1 + 0;
6411 zNear = r_refdef.nearclip;
6412 nudge = 1.0 - 1.0 / (1<<23);
6413 r_refdef.view.frustum[4].normal[0] = 0 - 0;
6414 r_refdef.view.frustum[4].normal[1] = 0 - 0;
6415 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6416 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6417 r_refdef.view.frustum[5].normal[0] = 0 + 0;
6418 r_refdef.view.frustum[5].normal[1] = 0 + 0;
6419 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6420 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6426 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6427 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6428 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6429 r_refdef.view.frustum[0].dist = m[15] - m[12];
6431 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6432 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6433 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6434 r_refdef.view.frustum[1].dist = m[15] + m[12];
6436 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6437 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6438 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6439 r_refdef.view.frustum[2].dist = m[15] - m[13];
6441 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6442 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6443 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6444 r_refdef.view.frustum[3].dist = m[15] + m[13];
6446 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6447 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6448 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6449 r_refdef.view.frustum[4].dist = m[15] - m[14];
6451 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6452 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6453 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6454 r_refdef.view.frustum[5].dist = m[15] + m[14];
6457 if (r_refdef.view.useperspective)
6459 slopex = 1.0 / r_refdef.view.frustum_x;
6460 slopey = 1.0 / r_refdef.view.frustum_y;
6461 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6462 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
6463 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
6464 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
6465 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6467 // Leaving those out was a mistake, those were in the old code, and they
6468 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6469 // I couldn't reproduce it after adding those normalizations. --blub
6470 VectorNormalize(r_refdef.view.frustum[0].normal);
6471 VectorNormalize(r_refdef.view.frustum[1].normal);
6472 VectorNormalize(r_refdef.view.frustum[2].normal);
6473 VectorNormalize(r_refdef.view.frustum[3].normal);
6475 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
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[0]);
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[1]);
6478 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]);
6479 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]);
6481 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6482 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6483 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6484 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6485 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6489 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6490 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6491 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6492 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6493 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6494 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6495 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6496 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6497 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6498 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6500 r_refdef.view.numfrustumplanes = 5;
6502 if (r_refdef.view.useclipplane)
6504 r_refdef.view.numfrustumplanes = 6;
6505 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6508 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6509 PlaneClassify(r_refdef.view.frustum + i);
6511 // LordHavoc: note to all quake engine coders, Quake had a special case
6512 // for 90 degrees which assumed a square view (wrong), so I removed it,
6513 // Quake2 has it disabled as well.
6515 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6516 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6517 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6518 //PlaneClassify(&frustum[0]);
6520 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6521 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6522 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6523 //PlaneClassify(&frustum[1]);
6525 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6526 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6527 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6528 //PlaneClassify(&frustum[2]);
6530 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6531 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6532 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6533 //PlaneClassify(&frustum[3]);
6536 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6537 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6538 //PlaneClassify(&frustum[4]);
6541 void R_View_Update(void)
6543 R_Main_ResizeViewCache();
6544 R_View_SetFrustum();
6545 R_View_WorldVisibility(r_refdef.view.useclipplane);
6546 R_View_UpdateEntityVisible();
6547 R_View_UpdateEntityLighting();
6550 void R_SetupView(qboolean allowwaterclippingplane)
6552 const float *customclipplane = NULL;
6554 if (r_refdef.view.useclipplane && allowwaterclippingplane)
6556 // LordHavoc: couldn't figure out how to make this approach the
6557 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6558 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6559 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6560 dist = r_refdef.view.clipplane.dist;
6561 plane[0] = r_refdef.view.clipplane.normal[0];
6562 plane[1] = r_refdef.view.clipplane.normal[1];
6563 plane[2] = r_refdef.view.clipplane.normal[2];
6565 customclipplane = plane;
6568 if (!r_refdef.view.useperspective)
6569 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);
6570 else if (vid.stencil && r_useinfinitefarclip.integer)
6571 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);
6573 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);
6574 R_SetViewport(&r_refdef.view.viewport);
6577 void R_EntityMatrix(const matrix4x4_t *matrix)
6579 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6581 gl_modelmatrixchanged = false;
6582 gl_modelmatrix = *matrix;
6583 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6584 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6585 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6586 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6588 switch(vid.renderpath)
6590 case RENDERPATH_GL20:
6591 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6592 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6593 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6595 case RENDERPATH_CGGL:
6598 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6599 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6600 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6603 case RENDERPATH_GL13:
6604 case RENDERPATH_GL11:
6605 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6611 void R_ResetViewRendering2D(void)
6613 r_viewport_t viewport;
6616 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6617 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);
6618 R_SetViewport(&viewport);
6619 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6620 GL_Color(1, 1, 1, 1);
6621 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6622 GL_BlendFunc(GL_ONE, GL_ZERO);
6623 GL_AlphaTest(false);
6624 GL_ScissorTest(false);
6625 GL_DepthMask(false);
6626 GL_DepthRange(0, 1);
6627 GL_DepthTest(false);
6628 R_EntityMatrix(&identitymatrix);
6629 R_Mesh_ResetTextureState();
6630 GL_PolygonOffset(0, 0);
6631 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6632 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6633 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6634 qglStencilMask(~0);CHECKGLERROR
6635 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6636 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6637 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6640 void R_ResetViewRendering3D(void)
6645 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6646 GL_Color(1, 1, 1, 1);
6647 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6648 GL_BlendFunc(GL_ONE, GL_ZERO);
6649 GL_AlphaTest(false);
6650 GL_ScissorTest(true);
6652 GL_DepthRange(0, 1);
6654 R_EntityMatrix(&identitymatrix);
6655 R_Mesh_ResetTextureState();
6656 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6657 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6658 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6659 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6660 qglStencilMask(~0);CHECKGLERROR
6661 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6662 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6663 GL_CullFace(r_refdef.view.cullface_back);
6666 void R_RenderScene(void);
6667 void R_RenderWaterPlanes(void);
6669 static void R_Water_StartFrame(void)
6672 int waterwidth, waterheight, texturewidth, textureheight;
6673 r_waterstate_waterplane_t *p;
6675 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6678 switch(vid.renderpath)
6680 case RENDERPATH_GL20:
6681 case RENDERPATH_CGGL:
6683 case RENDERPATH_GL13:
6684 case RENDERPATH_GL11:
6688 // set waterwidth and waterheight to the water resolution that will be
6689 // used (often less than the screen resolution for faster rendering)
6690 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6691 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6693 // calculate desired texture sizes
6694 // can't use water if the card does not support the texture size
6695 if (!r_water.integer || r_showsurfaces.integer)
6696 texturewidth = textureheight = waterwidth = waterheight = 0;
6697 else if (vid.support.arb_texture_non_power_of_two)
6699 texturewidth = waterwidth;
6700 textureheight = waterheight;
6704 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
6705 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
6708 // allocate textures as needed
6709 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6711 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6712 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6714 if (p->texture_refraction)
6715 R_FreeTexture(p->texture_refraction);
6716 p->texture_refraction = NULL;
6717 if (p->texture_reflection)
6718 R_FreeTexture(p->texture_reflection);
6719 p->texture_reflection = NULL;
6721 memset(&r_waterstate, 0, sizeof(r_waterstate));
6722 r_waterstate.texturewidth = texturewidth;
6723 r_waterstate.textureheight = textureheight;
6726 if (r_waterstate.texturewidth)
6728 r_waterstate.enabled = true;
6730 // when doing a reduced render (HDR) we want to use a smaller area
6731 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6732 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6734 // set up variables that will be used in shader setup
6735 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6736 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6737 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6738 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6741 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6742 r_waterstate.numwaterplanes = 0;
6745 void R_Water_AddWaterPlane(msurface_t *surface)
6747 int triangleindex, planeindex;
6753 r_waterstate_waterplane_t *p;
6754 texture_t *t = R_GetCurrentTexture(surface->texture);
6755 // just use the first triangle with a valid normal for any decisions
6756 VectorClear(normal);
6757 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6759 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6760 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6761 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6762 TriangleNormal(vert[0], vert[1], vert[2], normal);
6763 if (VectorLength2(normal) >= 0.001)
6767 VectorCopy(normal, plane.normal);
6768 VectorNormalize(plane.normal);
6769 plane.dist = DotProduct(vert[0], plane.normal);
6770 PlaneClassify(&plane);
6771 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6773 // skip backfaces (except if nocullface is set)
6774 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6776 VectorNegate(plane.normal, plane.normal);
6778 PlaneClassify(&plane);
6782 // find a matching plane if there is one
6783 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6784 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6786 if (planeindex >= r_waterstate.maxwaterplanes)
6787 return; // nothing we can do, out of planes
6789 // if this triangle does not fit any known plane rendered this frame, add one
6790 if (planeindex >= r_waterstate.numwaterplanes)
6792 // store the new plane
6793 r_waterstate.numwaterplanes++;
6795 // clear materialflags and pvs
6796 p->materialflags = 0;
6797 p->pvsvalid = false;
6799 // merge this surface's materialflags into the waterplane
6800 p->materialflags |= t->currentmaterialflags;
6801 // merge this surface's PVS into the waterplane
6802 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6803 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6804 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6806 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6811 static void R_Water_ProcessPlanes(void)
6813 r_refdef_view_t originalview;
6814 r_refdef_view_t myview;
6816 r_waterstate_waterplane_t *p;
6818 originalview = r_refdef.view;
6820 // make sure enough textures are allocated
6821 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6823 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6825 if (!p->texture_refraction)
6826 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);
6827 if (!p->texture_refraction)
6831 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6833 if (!p->texture_reflection)
6834 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);
6835 if (!p->texture_reflection)
6841 r_refdef.view = originalview;
6842 r_refdef.view.showdebug = false;
6843 r_refdef.view.width = r_waterstate.waterwidth;
6844 r_refdef.view.height = r_waterstate.waterheight;
6845 r_refdef.view.useclipplane = true;
6846 myview = r_refdef.view;
6847 r_waterstate.renderingscene = true;
6848 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6850 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6852 r_refdef.view = myview;
6853 // render reflected scene and copy into texture
6854 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6855 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6856 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6857 r_refdef.view.clipplane = p->plane;
6858 // reverse the cullface settings for this render
6859 r_refdef.view.cullface_front = GL_FRONT;
6860 r_refdef.view.cullface_back = GL_BACK;
6861 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6863 r_refdef.view.usecustompvs = true;
6865 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6867 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6870 R_ResetViewRendering3D();
6871 R_ClearScreen(r_refdef.fogenabled);
6875 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);
6878 // render the normal view scene and copy into texture
6879 // (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)
6880 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6882 r_refdef.view = myview;
6883 r_refdef.view.clipplane = p->plane;
6884 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6885 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6886 PlaneClassify(&r_refdef.view.clipplane);
6888 R_ResetViewRendering3D();
6889 R_ClearScreen(r_refdef.fogenabled);
6893 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);
6897 r_waterstate.renderingscene = false;
6898 r_refdef.view = originalview;
6899 R_ResetViewRendering3D();
6900 R_ClearScreen(r_refdef.fogenabled);
6904 r_refdef.view = originalview;
6905 r_waterstate.renderingscene = false;
6906 Cvar_SetValueQuick(&r_water, 0);
6907 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6911 void R_Bloom_StartFrame(void)
6913 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6915 switch(vid.renderpath)
6917 case RENDERPATH_GL20:
6918 case RENDERPATH_CGGL:
6920 case RENDERPATH_GL13:
6921 case RENDERPATH_GL11:
6925 // set bloomwidth and bloomheight to the bloom resolution that will be
6926 // used (often less than the screen resolution for faster rendering)
6927 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6928 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6929 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6930 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6931 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6933 // calculate desired texture sizes
6934 if (vid.support.arb_texture_non_power_of_two)
6936 screentexturewidth = r_refdef.view.width;
6937 screentextureheight = r_refdef.view.height;
6938 bloomtexturewidth = r_bloomstate.bloomwidth;
6939 bloomtextureheight = r_bloomstate.bloomheight;
6943 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6944 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6945 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
6946 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
6949 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))
6951 Cvar_SetValueQuick(&r_hdr, 0);
6952 Cvar_SetValueQuick(&r_bloom, 0);
6953 Cvar_SetValueQuick(&r_motionblur, 0);
6954 Cvar_SetValueQuick(&r_damageblur, 0);
6957 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)))
6958 screentexturewidth = screentextureheight = 0;
6959 if (!r_hdr.integer && !r_bloom.integer)
6960 bloomtexturewidth = bloomtextureheight = 0;
6962 // allocate textures as needed
6963 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
6965 if (r_bloomstate.texture_screen)
6966 R_FreeTexture(r_bloomstate.texture_screen);
6967 r_bloomstate.texture_screen = NULL;
6968 r_bloomstate.screentexturewidth = screentexturewidth;
6969 r_bloomstate.screentextureheight = screentextureheight;
6970 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6971 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
6973 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
6975 if (r_bloomstate.texture_bloom)
6976 R_FreeTexture(r_bloomstate.texture_bloom);
6977 r_bloomstate.texture_bloom = NULL;
6978 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6979 r_bloomstate.bloomtextureheight = bloomtextureheight;
6980 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6981 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6984 // when doing a reduced render (HDR) we want to use a smaller area
6985 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6986 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6987 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6988 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6989 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6991 // set up a texcoord array for the full resolution screen image
6992 // (we have to keep this around to copy back during final render)
6993 r_bloomstate.screentexcoord2f[0] = 0;
6994 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
6995 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
6996 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
6997 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
6998 r_bloomstate.screentexcoord2f[5] = 0;
6999 r_bloomstate.screentexcoord2f[6] = 0;
7000 r_bloomstate.screentexcoord2f[7] = 0;
7002 // set up a texcoord array for the reduced resolution bloom image
7003 // (which will be additive blended over the screen image)
7004 r_bloomstate.bloomtexcoord2f[0] = 0;
7005 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7006 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7007 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7008 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7009 r_bloomstate.bloomtexcoord2f[5] = 0;
7010 r_bloomstate.bloomtexcoord2f[6] = 0;
7011 r_bloomstate.bloomtexcoord2f[7] = 0;
7013 if (r_hdr.integer || r_bloom.integer)
7015 r_bloomstate.enabled = true;
7016 r_bloomstate.hdr = r_hdr.integer != 0;
7019 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);
7022 void R_Bloom_CopyBloomTexture(float colorscale)
7024 r_refdef.stats.bloom++;
7026 // scale down screen texture to the bloom texture size
7028 R_SetViewport(&r_bloomstate.viewport);
7029 GL_BlendFunc(GL_ONE, GL_ZERO);
7030 GL_Color(colorscale, colorscale, colorscale, 1);
7031 // TODO: optimize with multitexture or GLSL
7032 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7033 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7034 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7035 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7037 // we now have a bloom image in the framebuffer
7038 // copy it into the bloom image texture for later processing
7039 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);
7040 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7043 void R_Bloom_CopyHDRTexture(void)
7045 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);
7046 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7049 void R_Bloom_MakeTexture(void)
7052 float xoffset, yoffset, r, brighten;
7054 r_refdef.stats.bloom++;
7056 R_ResetViewRendering2D();
7057 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7058 R_Mesh_ColorPointer(NULL, 0, 0);
7060 // we have a bloom image in the framebuffer
7062 R_SetViewport(&r_bloomstate.viewport);
7064 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7067 r = bound(0, r_bloom_colorexponent.value / x, 1);
7068 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7069 GL_Color(r, r, r, 1);
7070 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7071 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7072 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7073 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7075 // copy the vertically blurred bloom view to a texture
7076 GL_ActiveTexture(0);
7078 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7079 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7082 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7083 brighten = r_bloom_brighten.value;
7085 brighten *= r_hdr_range.value;
7086 brighten = sqrt(brighten);
7088 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7089 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7090 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7092 for (dir = 0;dir < 2;dir++)
7094 // blend on at multiple vertical offsets to achieve a vertical blur
7095 // TODO: do offset blends using GLSL
7096 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7097 GL_BlendFunc(GL_ONE, GL_ZERO);
7098 for (x = -range;x <= range;x++)
7100 if (!dir){xoffset = 0;yoffset = x;}
7101 else {xoffset = x;yoffset = 0;}
7102 xoffset /= (float)r_bloomstate.bloomtexturewidth;
7103 yoffset /= (float)r_bloomstate.bloomtextureheight;
7104 // compute a texcoord array with the specified x and y offset
7105 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7106 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7107 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7108 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7109 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7110 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7111 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7112 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7113 // this r value looks like a 'dot' particle, fading sharply to
7114 // black at the edges
7115 // (probably not realistic but looks good enough)
7116 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7117 //r = brighten/(range*2+1);
7118 r = brighten / (range * 2 + 1);
7120 r *= (1 - x*x/(float)(range*range));
7121 GL_Color(r, r, r, 1);
7122 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7123 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7124 GL_BlendFunc(GL_ONE, GL_ONE);
7127 // copy the vertically blurred bloom view to a texture
7128 GL_ActiveTexture(0);
7130 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7131 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7134 // apply subtract last
7135 // (just like it would be in a GLSL shader)
7136 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7138 GL_BlendFunc(GL_ONE, GL_ZERO);
7139 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7140 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7141 GL_Color(1, 1, 1, 1);
7142 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7143 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7145 GL_BlendFunc(GL_ONE, GL_ONE);
7146 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7147 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7148 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7149 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7150 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7151 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7152 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7154 // copy the darkened bloom view to a texture
7155 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);
7156 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7160 void R_HDR_RenderBloomTexture(void)
7162 int oldwidth, oldheight;
7163 float oldcolorscale;
7165 oldcolorscale = r_refdef.view.colorscale;
7166 oldwidth = r_refdef.view.width;
7167 oldheight = r_refdef.view.height;
7168 r_refdef.view.width = r_bloomstate.bloomwidth;
7169 r_refdef.view.height = r_bloomstate.bloomheight;
7171 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
7172 // TODO: add exposure compensation features
7173 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7175 r_refdef.view.showdebug = false;
7176 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7178 R_ResetViewRendering3D();
7180 R_ClearScreen(r_refdef.fogenabled);
7181 if (r_timereport_active)
7182 R_TimeReport("HDRclear");
7185 if (r_timereport_active)
7186 R_TimeReport("visibility");
7188 // only do secondary renders with HDR if r_hdr is 2 or higher
7189 r_waterstate.numwaterplanes = 0;
7190 if (r_waterstate.enabled && r_hdr.integer >= 2)
7191 R_RenderWaterPlanes();
7193 r_refdef.view.showdebug = true;
7195 r_waterstate.numwaterplanes = 0;
7197 R_ResetViewRendering2D();
7199 R_Bloom_CopyHDRTexture();
7200 R_Bloom_MakeTexture();
7202 // restore the view settings
7203 r_refdef.view.width = oldwidth;
7204 r_refdef.view.height = oldheight;
7205 r_refdef.view.colorscale = oldcolorscale;
7206 r_frame++; // used only by R_GetCurrentTexture
7208 R_ResetViewRendering3D();
7210 R_ClearScreen(r_refdef.fogenabled);
7211 if (r_timereport_active)
7212 R_TimeReport("viewclear");
7215 static void R_BlendView(void)
7217 unsigned int permutation;
7218 float uservecs[4][4];
7220 switch (vid.renderpath)
7222 case RENDERPATH_GL20:
7223 case RENDERPATH_CGGL:
7225 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7226 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7227 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7228 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7229 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7231 if (r_bloomstate.texture_screen)
7233 // make sure the buffer is available
7234 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7236 R_ResetViewRendering2D();
7237 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7238 R_Mesh_ColorPointer(NULL, 0, 0);
7240 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7242 // declare variables
7244 static float avgspeed;
7246 speed = VectorLength(cl.movement_velocity);
7248 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7249 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7251 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7252 speed = bound(0, speed, 1);
7253 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7255 // calculate values into a standard alpha
7256 cl.motionbluralpha = 1 - exp(-
7258 (r_motionblur.value * speed / 80)
7260 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7263 max(0.0001, cl.time - cl.oldtime) // fps independent
7266 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7267 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7269 if (cl.motionbluralpha > 0)
7271 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7272 GL_Color(1, 1, 1, cl.motionbluralpha);
7273 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7274 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7275 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7276 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7280 // copy view into the screen texture
7281 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);
7282 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7284 else if (!r_bloomstate.texture_bloom)
7286 // we may still have to do view tint...
7287 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7289 // apply a color tint to the whole view
7290 R_ResetViewRendering2D();
7291 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7292 R_Mesh_ColorPointer(NULL, 0, 0);
7293 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7294 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7295 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7296 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7298 break; // no screen processing, no bloom, skip it
7301 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7303 // render simple bloom effect
7304 // copy the screen and shrink it and darken it for the bloom process
7305 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7306 // make the bloom texture
7307 R_Bloom_MakeTexture();
7310 #if _MSC_VER >= 1400
7311 #define sscanf sscanf_s
7313 memset(uservecs, 0, sizeof(uservecs));
7314 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7315 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7316 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7317 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7319 R_ResetViewRendering2D();
7320 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7321 R_Mesh_ColorPointer(NULL, 0, 0);
7322 GL_Color(1, 1, 1, 1);
7323 GL_BlendFunc(GL_ONE, GL_ZERO);
7324 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7325 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7327 switch(vid.renderpath)
7329 case RENDERPATH_GL20:
7330 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7331 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
7332 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
7333 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7334 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]);
7335 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime , cl.time);
7336 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7337 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]);
7338 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]);
7339 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]);
7340 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]);
7341 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7343 case RENDERPATH_CGGL:
7345 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7346 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
7347 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
7348 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
7349 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
7350 if (r_cg_permutation->fp_ClientTime ) cgGLSetParameter1f( r_cg_permutation->fp_ClientTime , cl.time);CHECKCGERROR
7351 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7352 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
7353 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
7354 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
7355 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
7356 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
7362 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7363 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7365 case RENDERPATH_GL13:
7366 case RENDERPATH_GL11:
7367 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7369 // apply a color tint to the whole view
7370 R_ResetViewRendering2D();
7371 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7372 R_Mesh_ColorPointer(NULL, 0, 0);
7373 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7374 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7375 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7376 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7382 matrix4x4_t r_waterscrollmatrix;
7384 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7386 if (r_refdef.fog_density)
7388 r_refdef.fogcolor[0] = r_refdef.fog_red;
7389 r_refdef.fogcolor[1] = r_refdef.fog_green;
7390 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7392 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7393 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7394 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7395 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7399 VectorCopy(r_refdef.fogcolor, fogvec);
7400 // color.rgb *= ContrastBoost * SceneBrightness;
7401 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7402 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7403 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7404 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7409 void R_UpdateVariables(void)
7413 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7415 r_refdef.farclip = r_farclip_base.value;
7416 if (r_refdef.scene.worldmodel)
7417 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7418 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7420 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7421 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7422 r_refdef.polygonfactor = 0;
7423 r_refdef.polygonoffset = 0;
7424 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7425 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7427 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7428 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7429 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7430 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7431 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7432 if (r_showsurfaces.integer)
7434 r_refdef.scene.rtworld = false;
7435 r_refdef.scene.rtworldshadows = false;
7436 r_refdef.scene.rtdlight = false;
7437 r_refdef.scene.rtdlightshadows = false;
7438 r_refdef.lightmapintensity = 0;
7441 if (gamemode == GAME_NEHAHRA)
7443 if (gl_fogenable.integer)
7445 r_refdef.oldgl_fogenable = true;
7446 r_refdef.fog_density = gl_fogdensity.value;
7447 r_refdef.fog_red = gl_fogred.value;
7448 r_refdef.fog_green = gl_foggreen.value;
7449 r_refdef.fog_blue = gl_fogblue.value;
7450 r_refdef.fog_alpha = 1;
7451 r_refdef.fog_start = 0;
7452 r_refdef.fog_end = gl_skyclip.value;
7453 r_refdef.fog_height = 1<<30;
7454 r_refdef.fog_fadedepth = 128;
7456 else if (r_refdef.oldgl_fogenable)
7458 r_refdef.oldgl_fogenable = false;
7459 r_refdef.fog_density = 0;
7460 r_refdef.fog_red = 0;
7461 r_refdef.fog_green = 0;
7462 r_refdef.fog_blue = 0;
7463 r_refdef.fog_alpha = 0;
7464 r_refdef.fog_start = 0;
7465 r_refdef.fog_end = 0;
7466 r_refdef.fog_height = 1<<30;
7467 r_refdef.fog_fadedepth = 128;
7471 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7472 r_refdef.fog_start = max(0, r_refdef.fog_start);
7473 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7475 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7477 if (r_refdef.fog_density && r_drawfog.integer)
7479 r_refdef.fogenabled = true;
7480 // this is the point where the fog reaches 0.9986 alpha, which we
7481 // consider a good enough cutoff point for the texture
7482 // (0.9986 * 256 == 255.6)
7483 if (r_fog_exp2.integer)
7484 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7486 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7487 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7488 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7489 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7490 // fog color was already set
7491 // update the fog texture
7492 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)
7493 R_BuildFogTexture();
7496 r_refdef.fogenabled = false;
7498 switch(vid.renderpath)
7500 case RENDERPATH_GL20:
7501 case RENDERPATH_CGGL:
7502 if(v_glslgamma.integer && !vid_gammatables_trivial)
7504 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7506 // build GLSL gamma texture
7507 #define RAMPWIDTH 256
7508 unsigned short ramp[RAMPWIDTH * 3];
7509 unsigned char rampbgr[RAMPWIDTH][4];
7512 r_texture_gammaramps_serial = vid_gammatables_serial;
7514 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7515 for(i = 0; i < RAMPWIDTH; ++i)
7517 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7518 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7519 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7522 if (r_texture_gammaramps)
7524 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7528 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);
7534 // remove GLSL gamma texture
7537 case RENDERPATH_GL13:
7538 case RENDERPATH_GL11:
7543 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7544 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7550 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7551 if( scenetype != r_currentscenetype ) {
7552 // store the old scenetype
7553 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7554 r_currentscenetype = scenetype;
7555 // move in the new scene
7556 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7565 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7567 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7568 if( scenetype == r_currentscenetype ) {
7569 return &r_refdef.scene;
7571 return &r_scenes_store[ scenetype ];
7580 void R_RenderView(void)
7582 if (r_timereport_active)
7583 R_TimeReport("start");
7584 r_frame++; // used only by R_GetCurrentTexture
7585 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7587 if (!r_drawentities.integer)
7588 r_refdef.scene.numentities = 0;
7590 R_AnimCache_ClearCache();
7591 R_FrameData_NewFrame();
7593 if (r_refdef.view.isoverlay)
7595 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7596 GL_Clear( GL_DEPTH_BUFFER_BIT );
7597 R_TimeReport("depthclear");
7599 r_refdef.view.showdebug = false;
7601 r_waterstate.enabled = false;
7602 r_waterstate.numwaterplanes = 0;
7610 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7611 return; //Host_Error ("R_RenderView: NULL worldmodel");
7613 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7615 // break apart the view matrix into vectors for various purposes
7616 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7617 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7618 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7619 VectorNegate(r_refdef.view.left, r_refdef.view.right);
7620 // make an inverted copy of the view matrix for tracking sprites
7621 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7623 R_Shadow_UpdateWorldLightSelection();
7625 R_Bloom_StartFrame();
7626 R_Water_StartFrame();
7629 if (r_timereport_active)
7630 R_TimeReport("viewsetup");
7632 R_ResetViewRendering3D();
7634 if (r_refdef.view.clear || r_refdef.fogenabled)
7636 R_ClearScreen(r_refdef.fogenabled);
7637 if (r_timereport_active)
7638 R_TimeReport("viewclear");
7640 r_refdef.view.clear = true;
7642 // this produces a bloom texture to be used in R_BlendView() later
7643 if (r_hdr.integer && r_bloomstate.bloomwidth)
7644 R_HDR_RenderBloomTexture();
7646 r_refdef.view.showdebug = true;
7649 if (r_timereport_active)
7650 R_TimeReport("visibility");
7652 r_waterstate.numwaterplanes = 0;
7653 if (r_waterstate.enabled)
7654 R_RenderWaterPlanes();
7657 r_waterstate.numwaterplanes = 0;
7660 if (r_timereport_active)
7661 R_TimeReport("blendview");
7663 GL_Scissor(0, 0, vid.width, vid.height);
7664 GL_ScissorTest(false);
7668 void R_RenderWaterPlanes(void)
7670 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7672 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7673 if (r_timereport_active)
7674 R_TimeReport("waterworld");
7677 // don't let sound skip if going slow
7678 if (r_refdef.scene.extraupdate)
7681 R_DrawModelsAddWaterPlanes();
7682 if (r_timereport_active)
7683 R_TimeReport("watermodels");
7685 if (r_waterstate.numwaterplanes)
7687 R_Water_ProcessPlanes();
7688 if (r_timereport_active)
7689 R_TimeReport("waterscenes");
7693 extern void R_DrawLightningBeams (void);
7694 extern void VM_CL_AddPolygonsToMeshQueue (void);
7695 extern void R_DrawPortals (void);
7696 extern cvar_t cl_locs_show;
7697 static void R_DrawLocs(void);
7698 static void R_DrawEntityBBoxes(void);
7699 static void R_DrawModelDecals(void);
7700 extern cvar_t cl_decals_newsystem;
7701 extern qboolean r_shadow_usingdeferredprepass;
7702 void R_RenderScene(void)
7704 r_refdef.stats.renders++;
7708 // don't let sound skip if going slow
7709 if (r_refdef.scene.extraupdate)
7712 R_MeshQueue_BeginScene();
7716 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);
7718 if (cl.csqc_vidvars.drawworld)
7720 // don't let sound skip if going slow
7721 if (r_refdef.scene.extraupdate)
7724 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7726 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7727 if (r_timereport_active)
7728 R_TimeReport("worldsky");
7731 if (R_DrawBrushModelsSky() && r_timereport_active)
7732 R_TimeReport("bmodelsky");
7734 if (skyrendermasked && skyrenderlater)
7736 // we have to force off the water clipping plane while rendering sky
7740 if (r_timereport_active)
7741 R_TimeReport("sky");
7745 R_AnimCache_CacheVisibleEntities();
7746 if (r_timereport_active)
7747 R_TimeReport("animation");
7749 R_Shadow_PrepareLights();
7750 if (r_timereport_active)
7751 R_TimeReport("preparelights");
7753 if (r_shadow_usingdeferredprepass)
7754 R_Shadow_DrawPrepass();
7756 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7758 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7759 if (r_timereport_active)
7760 R_TimeReport("worlddepth");
7762 if (r_depthfirst.integer >= 2)
7764 R_DrawModelsDepth();
7765 if (r_timereport_active)
7766 R_TimeReport("modeldepth");
7769 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7771 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7772 if (r_timereport_active)
7773 R_TimeReport("world");
7776 // don't let sound skip if going slow
7777 if (r_refdef.scene.extraupdate)
7781 if (r_timereport_active)
7782 R_TimeReport("models");
7784 // don't let sound skip if going slow
7785 if (r_refdef.scene.extraupdate)
7788 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7790 R_DrawModelShadows();
7791 R_ResetViewRendering3D();
7792 // don't let sound skip if going slow
7793 if (r_refdef.scene.extraupdate)
7797 if (!r_shadow_usingdeferredprepass)
7799 R_Shadow_DrawLights();
7800 if (r_timereport_active)
7801 R_TimeReport("rtlights");
7804 // don't let sound skip if going slow
7805 if (r_refdef.scene.extraupdate)
7808 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7810 R_DrawModelShadows();
7811 R_ResetViewRendering3D();
7812 // don't let sound skip if going slow
7813 if (r_refdef.scene.extraupdate)
7817 if (cl.csqc_vidvars.drawworld)
7819 if (cl_decals_newsystem.integer)
7821 R_DrawModelDecals();
7822 if (r_timereport_active)
7823 R_TimeReport("modeldecals");
7828 if (r_timereport_active)
7829 R_TimeReport("decals");
7833 if (r_timereport_active)
7834 R_TimeReport("particles");
7837 if (r_timereport_active)
7838 R_TimeReport("explosions");
7840 R_DrawLightningBeams();
7841 if (r_timereport_active)
7842 R_TimeReport("lightning");
7845 VM_CL_AddPolygonsToMeshQueue();
7847 if (r_refdef.view.showdebug)
7849 if (cl_locs_show.integer)
7852 if (r_timereport_active)
7853 R_TimeReport("showlocs");
7856 if (r_drawportals.integer)
7859 if (r_timereport_active)
7860 R_TimeReport("portals");
7863 if (r_showbboxes.value > 0)
7865 R_DrawEntityBBoxes();
7866 if (r_timereport_active)
7867 R_TimeReport("bboxes");
7871 R_MeshQueue_RenderTransparent();
7872 if (r_timereport_active)
7873 R_TimeReport("drawtrans");
7875 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))
7877 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7878 if (r_timereport_active)
7879 R_TimeReport("worlddebug");
7880 R_DrawModelsDebug();
7881 if (r_timereport_active)
7882 R_TimeReport("modeldebug");
7885 if (cl.csqc_vidvars.drawworld)
7887 R_Shadow_DrawCoronas();
7888 if (r_timereport_active)
7889 R_TimeReport("coronas");
7892 // don't let sound skip if going slow
7893 if (r_refdef.scene.extraupdate)
7896 R_ResetViewRendering2D();
7899 static const unsigned short bboxelements[36] =
7909 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7912 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7914 RSurf_ActiveWorldEntity();
7916 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7917 GL_DepthMask(false);
7918 GL_DepthRange(0, 1);
7919 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7920 R_Mesh_ResetTextureState();
7922 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7923 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7924 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7925 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7926 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7927 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7928 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7929 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7930 R_FillColors(color4f, 8, cr, cg, cb, ca);
7931 if (r_refdef.fogenabled)
7933 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7935 f1 = RSurf_FogVertex(v);
7937 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7938 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7939 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7942 R_Mesh_VertexPointer(vertex3f, 0, 0);
7943 R_Mesh_ColorPointer(color4f, 0, 0);
7944 R_Mesh_ResetTextureState();
7945 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7946 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
7949 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7953 prvm_edict_t *edict;
7954 prvm_prog_t *prog_save = prog;
7956 // this function draws bounding boxes of server entities
7960 GL_CullFace(GL_NONE);
7961 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7965 for (i = 0;i < numsurfaces;i++)
7967 edict = PRVM_EDICT_NUM(surfacelist[i]);
7968 switch ((int)edict->fields.server->solid)
7970 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7971 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7972 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7973 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7974 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7975 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7977 color[3] *= r_showbboxes.value;
7978 color[3] = bound(0, color[3], 1);
7979 GL_DepthTest(!r_showdisabledepthtest.integer);
7980 GL_CullFace(r_refdef.view.cullface_front);
7981 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7987 static void R_DrawEntityBBoxes(void)
7990 prvm_edict_t *edict;
7992 prvm_prog_t *prog_save = prog;
7994 // this function draws bounding boxes of server entities
8000 for (i = 0;i < prog->num_edicts;i++)
8002 edict = PRVM_EDICT_NUM(i);
8003 if (edict->priv.server->free)
8005 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8006 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8008 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8010 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8011 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8017 static const int nomodelelement3i[24] =
8029 static const unsigned short nomodelelement3s[24] =
8041 static const float nomodelvertex3f[6*3] =
8051 static const float nomodelcolor4f[6*4] =
8053 0.0f, 0.0f, 0.5f, 1.0f,
8054 0.0f, 0.0f, 0.5f, 1.0f,
8055 0.0f, 0.5f, 0.0f, 1.0f,
8056 0.0f, 0.5f, 0.0f, 1.0f,
8057 0.5f, 0.0f, 0.0f, 1.0f,
8058 0.5f, 0.0f, 0.0f, 1.0f
8061 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8067 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);
8069 // this is only called once per entity so numsurfaces is always 1, and
8070 // surfacelist is always {0}, so this code does not handle batches
8072 if (rsurface.ent_flags & RENDER_ADDITIVE)
8074 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8075 GL_DepthMask(false);
8077 else if (rsurface.colormod[3] < 1)
8079 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8080 GL_DepthMask(false);
8084 GL_BlendFunc(GL_ONE, GL_ZERO);
8087 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8088 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8089 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8090 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8091 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8092 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8093 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8094 R_Mesh_ColorPointer(color4f, 0, 0);
8095 for (i = 0, c = color4f;i < 6;i++, c += 4)
8097 c[0] *= rsurface.colormod[0];
8098 c[1] *= rsurface.colormod[1];
8099 c[2] *= rsurface.colormod[2];
8100 c[3] *= rsurface.colormod[3];
8102 if (r_refdef.fogenabled)
8104 for (i = 0, c = color4f;i < 6;i++, c += 4)
8106 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8108 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8109 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8110 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8113 R_Mesh_ResetTextureState();
8114 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8117 void R_DrawNoModel(entity_render_t *ent)
8120 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8121 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8122 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8124 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8127 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8129 vec3_t right1, right2, diff, normal;
8131 VectorSubtract (org2, org1, normal);
8133 // calculate 'right' vector for start
8134 VectorSubtract (r_refdef.view.origin, org1, diff);
8135 CrossProduct (normal, diff, right1);
8136 VectorNormalize (right1);
8138 // calculate 'right' vector for end
8139 VectorSubtract (r_refdef.view.origin, org2, diff);
8140 CrossProduct (normal, diff, right2);
8141 VectorNormalize (right2);
8143 vert[ 0] = org1[0] + width * right1[0];
8144 vert[ 1] = org1[1] + width * right1[1];
8145 vert[ 2] = org1[2] + width * right1[2];
8146 vert[ 3] = org1[0] - width * right1[0];
8147 vert[ 4] = org1[1] - width * right1[1];
8148 vert[ 5] = org1[2] - width * right1[2];
8149 vert[ 6] = org2[0] - width * right2[0];
8150 vert[ 7] = org2[1] - width * right2[1];
8151 vert[ 8] = org2[2] - width * right2[2];
8152 vert[ 9] = org2[0] + width * right2[0];
8153 vert[10] = org2[1] + width * right2[1];
8154 vert[11] = org2[2] + width * right2[2];
8157 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)
8159 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8160 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8161 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8162 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8163 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8164 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8165 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8166 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8167 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8168 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8169 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8170 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8173 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8178 VectorSet(v, x, y, z);
8179 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8180 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8182 if (i == mesh->numvertices)
8184 if (mesh->numvertices < mesh->maxvertices)
8186 VectorCopy(v, vertex3f);
8187 mesh->numvertices++;
8189 return mesh->numvertices;
8195 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8199 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8200 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8201 e = mesh->element3i + mesh->numtriangles * 3;
8202 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8204 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8205 if (mesh->numtriangles < mesh->maxtriangles)
8210 mesh->numtriangles++;
8212 element[1] = element[2];
8216 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8220 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8221 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8222 e = mesh->element3i + mesh->numtriangles * 3;
8223 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8225 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8226 if (mesh->numtriangles < mesh->maxtriangles)
8231 mesh->numtriangles++;
8233 element[1] = element[2];
8237 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8238 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8240 int planenum, planenum2;
8243 mplane_t *plane, *plane2;
8245 double temppoints[2][256*3];
8246 // figure out how large a bounding box we need to properly compute this brush
8248 for (w = 0;w < numplanes;w++)
8249 maxdist = max(maxdist, fabs(planes[w].dist));
8250 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8251 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8252 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8256 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8257 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8259 if (planenum2 == planenum)
8261 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);
8264 if (tempnumpoints < 3)
8266 // generate elements forming a triangle fan for this polygon
8267 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8271 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)
8273 texturelayer_t *layer;
8274 layer = t->currentlayers + t->currentnumlayers++;
8276 layer->depthmask = depthmask;
8277 layer->blendfunc1 = blendfunc1;
8278 layer->blendfunc2 = blendfunc2;
8279 layer->texture = texture;
8280 layer->texmatrix = *matrix;
8281 layer->color[0] = r;
8282 layer->color[1] = g;
8283 layer->color[2] = b;
8284 layer->color[3] = a;
8287 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8290 index = parms[2] + r_refdef.scene.time * parms[3];
8291 index -= floor(index);
8295 case Q3WAVEFUNC_NONE:
8296 case Q3WAVEFUNC_NOISE:
8297 case Q3WAVEFUNC_COUNT:
8300 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8301 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8302 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8303 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8304 case Q3WAVEFUNC_TRIANGLE:
8306 f = index - floor(index);
8317 return (float)(parms[0] + parms[1] * f);
8320 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8325 matrix4x4_t matrix, temp;
8326 switch(tcmod->tcmod)
8330 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8331 matrix = r_waterscrollmatrix;
8333 matrix = identitymatrix;
8335 case Q3TCMOD_ENTITYTRANSLATE:
8336 // this is used in Q3 to allow the gamecode to control texcoord
8337 // scrolling on the entity, which is not supported in darkplaces yet.
8338 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8340 case Q3TCMOD_ROTATE:
8341 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8342 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8343 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8346 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8348 case Q3TCMOD_SCROLL:
8349 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8351 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8352 w = (int) tcmod->parms[0];
8353 h = (int) tcmod->parms[1];
8354 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8356 idx = (int) floor(f * w * h);
8357 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8359 case Q3TCMOD_STRETCH:
8360 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8361 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8363 case Q3TCMOD_TRANSFORM:
8364 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8365 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8366 VectorSet(tcmat + 6, 0 , 0 , 1);
8367 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8368 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8370 case Q3TCMOD_TURBULENT:
8371 // this is handled in the RSurf_PrepareVertices function
8372 matrix = identitymatrix;
8376 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8379 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8381 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8382 char name[MAX_QPATH];
8383 skinframe_t *skinframe;
8384 unsigned char pixels[296*194];
8385 strlcpy(cache->name, skinname, sizeof(cache->name));
8386 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8387 if (developer_loading.integer)
8388 Con_Printf("loading %s\n", name);
8389 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8390 if (!skinframe || !skinframe->base)
8393 fs_offset_t filesize;
8395 f = FS_LoadFile(name, tempmempool, true, &filesize);
8398 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8399 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8403 cache->skinframe = skinframe;
8406 texture_t *R_GetCurrentTexture(texture_t *t)
8409 const entity_render_t *ent = rsurface.entity;
8410 dp_model_t *model = ent->model;
8411 q3shaderinfo_layer_tcmod_t *tcmod;
8413 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
8414 return t->currentframe;
8415 t->update_lastrenderframe = r_frame;
8416 t->update_lastrenderentity = (void *)ent;
8418 // switch to an alternate material if this is a q1bsp animated material
8420 texture_t *texture = t;
8421 int s = rsurface.ent_skinnum;
8422 if ((unsigned int)s >= (unsigned int)model->numskins)
8424 if (model->skinscenes)
8426 if (model->skinscenes[s].framecount > 1)
8427 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8429 s = model->skinscenes[s].firstframe;
8432 t = t + s * model->num_surfaces;
8435 // use an alternate animation if the entity's frame is not 0,
8436 // and only if the texture has an alternate animation
8437 if (rsurface.ent_alttextures && t->anim_total[1])
8438 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8440 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8442 texture->currentframe = t;
8445 // update currentskinframe to be a qw skin or animation frame
8446 if (rsurface.ent_qwskin >= 0)
8448 i = rsurface.ent_qwskin;
8449 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8451 r_qwskincache_size = cl.maxclients;
8453 Mem_Free(r_qwskincache);
8454 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8456 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8457 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8458 t->currentskinframe = r_qwskincache[i].skinframe;
8459 if (t->currentskinframe == NULL)
8460 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8462 else if (t->numskinframes >= 2)
8463 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8464 if (t->backgroundnumskinframes >= 2)
8465 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8467 t->currentmaterialflags = t->basematerialflags;
8468 t->currentalpha = rsurface.colormod[3];
8469 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8470 t->currentalpha *= r_wateralpha.value;
8471 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8472 t->currentalpha *= t->r_water_wateralpha;
8473 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8474 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8475 if (!(rsurface.ent_flags & RENDER_LIGHT))
8476 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8477 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8479 // pick a model lighting mode
8480 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8481 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8483 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8485 if (rsurface.ent_flags & RENDER_ADDITIVE)
8486 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8487 else if (t->currentalpha < 1)
8488 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8489 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8490 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8491 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8492 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8493 if (t->backgroundnumskinframes)
8494 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8495 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8497 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8498 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8501 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8502 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8503 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8505 // there is no tcmod
8506 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8508 t->currenttexmatrix = r_waterscrollmatrix;
8509 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8511 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8513 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8514 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8517 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8518 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8519 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8520 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8522 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8523 if (t->currentskinframe->qpixels)
8524 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8525 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8526 if (!t->basetexture)
8527 t->basetexture = r_texture_notexture;
8528 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8529 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8530 t->nmaptexture = t->currentskinframe->nmap;
8531 if (!t->nmaptexture)
8532 t->nmaptexture = r_texture_blanknormalmap;
8533 t->glosstexture = r_texture_black;
8534 t->glowtexture = t->currentskinframe->glow;
8535 t->fogtexture = t->currentskinframe->fog;
8536 if (t->backgroundnumskinframes)
8538 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8539 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8540 t->backgroundglosstexture = r_texture_black;
8541 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8542 if (!t->backgroundnmaptexture)
8543 t->backgroundnmaptexture = r_texture_blanknormalmap;
8547 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8548 t->backgroundnmaptexture = r_texture_blanknormalmap;
8549 t->backgroundglosstexture = r_texture_black;
8550 t->backgroundglowtexture = NULL;
8552 t->specularpower = r_shadow_glossexponent.value;
8553 // TODO: store reference values for these in the texture?
8554 t->specularscale = 0;
8555 if (r_shadow_gloss.integer > 0)
8557 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8559 if (r_shadow_glossintensity.value > 0)
8561 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8562 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8563 t->specularscale = r_shadow_glossintensity.value;
8566 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8568 t->glosstexture = r_texture_white;
8569 t->backgroundglosstexture = r_texture_white;
8570 t->specularscale = r_shadow_gloss2intensity.value;
8571 t->specularpower = r_shadow_gloss2exponent.value;
8574 t->specularscale *= t->specularscalemod;
8575 t->specularpower *= t->specularpowermod;
8577 // lightmaps mode looks bad with dlights using actual texturing, so turn
8578 // off the colormap and glossmap, but leave the normalmap on as it still
8579 // accurately represents the shading involved
8580 if (gl_lightmaps.integer)
8582 t->basetexture = r_texture_grey128;
8583 t->pantstexture = r_texture_black;
8584 t->shirttexture = r_texture_black;
8585 t->nmaptexture = r_texture_blanknormalmap;
8586 t->glosstexture = r_texture_black;
8587 t->glowtexture = NULL;
8588 t->fogtexture = NULL;
8589 t->backgroundbasetexture = NULL;
8590 t->backgroundnmaptexture = r_texture_blanknormalmap;
8591 t->backgroundglosstexture = r_texture_black;
8592 t->backgroundglowtexture = NULL;
8593 t->specularscale = 0;
8594 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8597 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8598 VectorClear(t->dlightcolor);
8599 t->currentnumlayers = 0;
8600 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8602 int blendfunc1, blendfunc2;
8604 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8606 blendfunc1 = GL_SRC_ALPHA;
8607 blendfunc2 = GL_ONE;
8609 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8611 blendfunc1 = GL_SRC_ALPHA;
8612 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8614 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8616 blendfunc1 = t->customblendfunc[0];
8617 blendfunc2 = t->customblendfunc[1];
8621 blendfunc1 = GL_ONE;
8622 blendfunc2 = GL_ZERO;
8624 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8625 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8627 // fullbright is not affected by r_refdef.lightmapintensity
8628 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]);
8629 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8630 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]);
8631 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8632 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]);
8636 vec3_t ambientcolor;
8638 // set the color tint used for lights affecting this surface
8639 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8641 // q3bsp has no lightmap updates, so the lightstylevalue that
8642 // would normally be baked into the lightmap must be
8643 // applied to the color
8644 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8645 if (model->type == mod_brushq3)
8646 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8647 colorscale *= r_refdef.lightmapintensity;
8648 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8649 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8650 // basic lit geometry
8651 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]);
8652 // add pants/shirt if needed
8653 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8654 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]);
8655 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8656 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]);
8657 // now add ambient passes if needed
8658 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8660 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]);
8661 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8662 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]);
8663 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8664 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]);
8667 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8668 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]);
8669 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8671 // if this is opaque use alpha blend which will darken the earlier
8674 // if this is an alpha blended material, all the earlier passes
8675 // were darkened by fog already, so we only need to add the fog
8676 // color ontop through the fog mask texture
8678 // if this is an additive blended material, all the earlier passes
8679 // were darkened by fog already, and we should not add fog color
8680 // (because the background was not darkened, there is no fog color
8681 // that was lost behind it).
8682 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]);
8686 return t->currentframe;
8689 rsurfacestate_t rsurface;
8691 void R_Mesh_ResizeArrays(int newvertices)
8694 if (rsurface.array_size >= newvertices)
8696 if (rsurface.array_modelvertex3f)
8697 Mem_Free(rsurface.array_modelvertex3f);
8698 rsurface.array_size = (newvertices + 1023) & ~1023;
8699 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8700 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
8701 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
8702 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
8703 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
8704 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
8705 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8706 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8707 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
8708 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
8709 rsurface.array_color4f = base + rsurface.array_size * 27;
8710 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8713 void RSurf_ActiveWorldEntity(void)
8715 dp_model_t *model = r_refdef.scene.worldmodel;
8716 //if (rsurface.entity == r_refdef.scene.worldentity)
8718 rsurface.entity = r_refdef.scene.worldentity;
8719 rsurface.skeleton = NULL;
8720 rsurface.ent_skinnum = 0;
8721 rsurface.ent_qwskin = -1;
8722 rsurface.ent_shadertime = 0;
8723 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8724 if (rsurface.array_size < model->surfmesh.num_vertices)
8725 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8726 rsurface.matrix = identitymatrix;
8727 rsurface.inversematrix = identitymatrix;
8728 rsurface.matrixscale = 1;
8729 rsurface.inversematrixscale = 1;
8730 R_EntityMatrix(&identitymatrix);
8731 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8732 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8733 rsurface.fograngerecip = r_refdef.fograngerecip;
8734 rsurface.fogheightfade = r_refdef.fogheightfade;
8735 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8736 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8737 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8738 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8739 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8740 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8741 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8742 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8743 rsurface.colormod[3] = 1;
8744 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);
8745 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8746 rsurface.frameblend[0].lerp = 1;
8747 rsurface.ent_alttextures = false;
8748 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8749 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8750 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8751 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8752 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8753 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8754 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8755 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8756 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8757 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8758 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8759 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8760 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8761 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8762 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8763 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8764 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8765 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8766 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8767 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8768 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8769 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8770 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8771 rsurface.modelelement3i = model->surfmesh.data_element3i;
8772 rsurface.modelelement3s = model->surfmesh.data_element3s;
8773 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8774 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8775 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8776 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8777 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8778 rsurface.modelsurfaces = model->data_surfaces;
8779 rsurface.generatedvertex = false;
8780 rsurface.vertex3f = rsurface.modelvertex3f;
8781 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8782 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8783 rsurface.svector3f = rsurface.modelsvector3f;
8784 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8785 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8786 rsurface.tvector3f = rsurface.modeltvector3f;
8787 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8788 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8789 rsurface.normal3f = rsurface.modelnormal3f;
8790 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8791 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8792 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8795 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8797 dp_model_t *model = ent->model;
8798 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8800 rsurface.entity = (entity_render_t *)ent;
8801 rsurface.skeleton = ent->skeleton;
8802 rsurface.ent_skinnum = ent->skinnum;
8803 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;
8804 rsurface.ent_shadertime = ent->shadertime;
8805 rsurface.ent_flags = ent->flags;
8806 if (rsurface.array_size < model->surfmesh.num_vertices)
8807 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8808 rsurface.matrix = ent->matrix;
8809 rsurface.inversematrix = ent->inversematrix;
8810 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8811 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8812 R_EntityMatrix(&rsurface.matrix);
8813 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8814 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8815 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8816 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8817 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8818 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8819 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8820 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8821 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8822 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8823 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8824 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8825 rsurface.colormod[3] = ent->alpha;
8826 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8827 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8828 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8829 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8830 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8831 if (ent->model->brush.submodel && !prepass)
8833 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8834 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8836 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8838 if (ent->animcache_vertex3f && !r_framedata_failed)
8840 rsurface.modelvertex3f = ent->animcache_vertex3f;
8841 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8842 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8843 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8845 else if (wanttangents)
8847 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8848 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
8849 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
8850 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8851 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
8853 else if (wantnormals)
8855 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8856 rsurface.modelsvector3f = NULL;
8857 rsurface.modeltvector3f = NULL;
8858 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8859 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
8863 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8864 rsurface.modelsvector3f = NULL;
8865 rsurface.modeltvector3f = NULL;
8866 rsurface.modelnormal3f = NULL;
8867 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
8869 rsurface.modelvertex3f_bufferobject = 0;
8870 rsurface.modelvertex3f_bufferoffset = 0;
8871 rsurface.modelsvector3f_bufferobject = 0;
8872 rsurface.modelsvector3f_bufferoffset = 0;
8873 rsurface.modeltvector3f_bufferobject = 0;
8874 rsurface.modeltvector3f_bufferoffset = 0;
8875 rsurface.modelnormal3f_bufferobject = 0;
8876 rsurface.modelnormal3f_bufferoffset = 0;
8877 rsurface.generatedvertex = true;
8881 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8882 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8883 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8884 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8885 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8886 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8887 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8888 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8889 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8890 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8891 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8892 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8893 rsurface.generatedvertex = false;
8895 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8896 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8897 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8898 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8899 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8900 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8901 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8902 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8903 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8904 rsurface.modelelement3i = model->surfmesh.data_element3i;
8905 rsurface.modelelement3s = model->surfmesh.data_element3s;
8906 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8907 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8908 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8909 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8910 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8911 rsurface.modelsurfaces = model->data_surfaces;
8912 rsurface.vertex3f = rsurface.modelvertex3f;
8913 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8914 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8915 rsurface.svector3f = rsurface.modelsvector3f;
8916 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8917 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8918 rsurface.tvector3f = rsurface.modeltvector3f;
8919 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8920 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8921 rsurface.normal3f = rsurface.modelnormal3f;
8922 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8923 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8924 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8927 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)
8929 rsurface.entity = r_refdef.scene.worldentity;
8930 rsurface.skeleton = NULL;
8931 rsurface.ent_skinnum = 0;
8932 rsurface.ent_qwskin = -1;
8933 rsurface.ent_shadertime = shadertime;
8934 rsurface.ent_flags = entflags;
8935 rsurface.modelnum_vertices = numvertices;
8936 rsurface.modelnum_triangles = numtriangles;
8937 if (rsurface.array_size < rsurface.modelnum_vertices)
8938 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
8939 rsurface.matrix = *matrix;
8940 rsurface.inversematrix = *inversematrix;
8941 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8942 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8943 R_EntityMatrix(&rsurface.matrix);
8944 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8945 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8946 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8947 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8948 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8949 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8950 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8951 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8952 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8953 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8954 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8955 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8956 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);
8957 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8958 rsurface.frameblend[0].lerp = 1;
8959 rsurface.ent_alttextures = false;
8960 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8961 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8964 rsurface.modelvertex3f = vertex3f;
8965 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
8966 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
8967 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8969 else if (wantnormals)
8971 rsurface.modelvertex3f = vertex3f;
8972 rsurface.modelsvector3f = NULL;
8973 rsurface.modeltvector3f = NULL;
8974 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8978 rsurface.modelvertex3f = vertex3f;
8979 rsurface.modelsvector3f = NULL;
8980 rsurface.modeltvector3f = NULL;
8981 rsurface.modelnormal3f = NULL;
8983 rsurface.modelvertex3f_bufferobject = 0;
8984 rsurface.modelvertex3f_bufferoffset = 0;
8985 rsurface.modelsvector3f_bufferobject = 0;
8986 rsurface.modelsvector3f_bufferoffset = 0;
8987 rsurface.modeltvector3f_bufferobject = 0;
8988 rsurface.modeltvector3f_bufferoffset = 0;
8989 rsurface.modelnormal3f_bufferobject = 0;
8990 rsurface.modelnormal3f_bufferoffset = 0;
8991 rsurface.generatedvertex = true;
8992 rsurface.modellightmapcolor4f = color4f;
8993 rsurface.modellightmapcolor4f_bufferobject = 0;
8994 rsurface.modellightmapcolor4f_bufferoffset = 0;
8995 rsurface.modeltexcoordtexture2f = texcoord2f;
8996 rsurface.modeltexcoordtexture2f_bufferobject = 0;
8997 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8998 rsurface.modeltexcoordlightmap2f = NULL;
8999 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9000 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9001 rsurface.modelelement3i = element3i;
9002 rsurface.modelelement3s = element3s;
9003 rsurface.modelelement3i_bufferobject = 0;
9004 rsurface.modelelement3s_bufferobject = 0;
9005 rsurface.modellightmapoffsets = NULL;
9006 rsurface.modelsurfaces = NULL;
9007 rsurface.vertex3f = rsurface.modelvertex3f;
9008 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9009 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9010 rsurface.svector3f = rsurface.modelsvector3f;
9011 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9012 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9013 rsurface.tvector3f = rsurface.modeltvector3f;
9014 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9015 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9016 rsurface.normal3f = rsurface.modelnormal3f;
9017 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9018 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9019 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9021 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9023 if ((wantnormals || wanttangents) && !normal3f)
9024 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9025 if (wanttangents && !svector3f)
9026 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);
9030 float RSurf_FogPoint(const float *v)
9032 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9033 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9034 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9035 float FogHeightFade = r_refdef.fogheightfade;
9037 unsigned int fogmasktableindex;
9038 if (r_refdef.fogplaneviewabove)
9039 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9041 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9042 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9043 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9046 float RSurf_FogVertex(const float *v)
9048 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9049 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9050 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9051 float FogHeightFade = rsurface.fogheightfade;
9053 unsigned int fogmasktableindex;
9054 if (r_refdef.fogplaneviewabove)
9055 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9057 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9058 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9059 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9062 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9063 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9066 int texturesurfaceindex;
9071 const float *v1, *in_tc;
9073 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9075 q3shaderinfo_deform_t *deform;
9076 // 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
9077 if (rsurface.generatedvertex)
9079 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9080 generatenormals = true;
9081 for (i = 0;i < Q3MAXDEFORMS;i++)
9083 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9085 generatetangents = true;
9086 generatenormals = true;
9088 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9089 generatenormals = true;
9091 if (generatenormals && !rsurface.modelnormal3f)
9093 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9094 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9095 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9096 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9098 if (generatetangents && !rsurface.modelsvector3f)
9100 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9101 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9102 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9103 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9104 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9105 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9106 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);
9109 rsurface.vertex3f = rsurface.modelvertex3f;
9110 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9111 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9112 rsurface.svector3f = rsurface.modelsvector3f;
9113 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9114 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9115 rsurface.tvector3f = rsurface.modeltvector3f;
9116 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9117 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9118 rsurface.normal3f = rsurface.modelnormal3f;
9119 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9120 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9121 // if vertices are deformed (sprite flares and things in maps, possibly
9122 // water waves, bulges and other deformations), generate them into
9123 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9124 // (may be static model data or generated data for an animated model, or
9125 // the previous deform pass)
9126 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9128 switch (deform->deform)
9131 case Q3DEFORM_PROJECTIONSHADOW:
9132 case Q3DEFORM_TEXT0:
9133 case Q3DEFORM_TEXT1:
9134 case Q3DEFORM_TEXT2:
9135 case Q3DEFORM_TEXT3:
9136 case Q3DEFORM_TEXT4:
9137 case Q3DEFORM_TEXT5:
9138 case Q3DEFORM_TEXT6:
9139 case Q3DEFORM_TEXT7:
9142 case Q3DEFORM_AUTOSPRITE:
9143 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9144 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9145 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9146 VectorNormalize(newforward);
9147 VectorNormalize(newright);
9148 VectorNormalize(newup);
9149 // make deformed versions of only the model vertices used by the specified surfaces
9150 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9152 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9153 // a single autosprite surface can contain multiple sprites...
9154 for (j = 0;j < surface->num_vertices - 3;j += 4)
9156 VectorClear(center);
9157 for (i = 0;i < 4;i++)
9158 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9159 VectorScale(center, 0.25f, center);
9160 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9161 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9162 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9163 for (i = 0;i < 4;i++)
9165 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9166 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9169 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);
9170 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);
9172 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9173 rsurface.vertex3f_bufferobject = 0;
9174 rsurface.vertex3f_bufferoffset = 0;
9175 rsurface.svector3f = rsurface.array_deformedsvector3f;
9176 rsurface.svector3f_bufferobject = 0;
9177 rsurface.svector3f_bufferoffset = 0;
9178 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9179 rsurface.tvector3f_bufferobject = 0;
9180 rsurface.tvector3f_bufferoffset = 0;
9181 rsurface.normal3f = rsurface.array_deformednormal3f;
9182 rsurface.normal3f_bufferobject = 0;
9183 rsurface.normal3f_bufferoffset = 0;
9185 case Q3DEFORM_AUTOSPRITE2:
9186 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9187 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9188 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9189 VectorNormalize(newforward);
9190 VectorNormalize(newright);
9191 VectorNormalize(newup);
9192 // make deformed versions of only the model vertices used by the specified surfaces
9193 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9195 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9196 const float *v1, *v2;
9206 memset(shortest, 0, sizeof(shortest));
9207 // a single autosprite surface can contain multiple sprites...
9208 for (j = 0;j < surface->num_vertices - 3;j += 4)
9210 VectorClear(center);
9211 for (i = 0;i < 4;i++)
9212 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9213 VectorScale(center, 0.25f, center);
9214 // find the two shortest edges, then use them to define the
9215 // axis vectors for rotating around the central axis
9216 for (i = 0;i < 6;i++)
9218 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9219 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9221 Debug_PolygonBegin(NULL, 0);
9222 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9223 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);
9224 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9227 l = VectorDistance2(v1, v2);
9228 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9230 l += (1.0f / 1024.0f);
9231 if (shortest[0].length2 > l || i == 0)
9233 shortest[1] = shortest[0];
9234 shortest[0].length2 = l;
9235 shortest[0].v1 = v1;
9236 shortest[0].v2 = v2;
9238 else if (shortest[1].length2 > l || i == 1)
9240 shortest[1].length2 = l;
9241 shortest[1].v1 = v1;
9242 shortest[1].v2 = v2;
9245 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9246 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9248 Debug_PolygonBegin(NULL, 0);
9249 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9250 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);
9251 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9254 // this calculates the right vector from the shortest edge
9255 // and the up vector from the edge midpoints
9256 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9257 VectorNormalize(right);
9258 VectorSubtract(end, start, up);
9259 VectorNormalize(up);
9260 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9261 VectorSubtract(rsurface.localvieworigin, center, forward);
9262 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9263 VectorNegate(forward, forward);
9264 VectorReflect(forward, 0, up, forward);
9265 VectorNormalize(forward);
9266 CrossProduct(up, forward, newright);
9267 VectorNormalize(newright);
9269 Debug_PolygonBegin(NULL, 0);
9270 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);
9271 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9272 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9276 Debug_PolygonBegin(NULL, 0);
9277 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9278 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9279 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9282 // rotate the quad around the up axis vector, this is made
9283 // especially easy by the fact we know the quad is flat,
9284 // so we only have to subtract the center position and
9285 // measure distance along the right vector, and then
9286 // multiply that by the newright vector and add back the
9288 // we also need to subtract the old position to undo the
9289 // displacement from the center, which we do with a
9290 // DotProduct, the subtraction/addition of center is also
9291 // optimized into DotProducts here
9292 l = DotProduct(right, center);
9293 for (i = 0;i < 4;i++)
9295 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9296 f = DotProduct(right, v1) - l;
9297 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9300 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);
9301 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);
9303 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9304 rsurface.vertex3f_bufferobject = 0;
9305 rsurface.vertex3f_bufferoffset = 0;
9306 rsurface.svector3f = rsurface.array_deformedsvector3f;
9307 rsurface.svector3f_bufferobject = 0;
9308 rsurface.svector3f_bufferoffset = 0;
9309 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9310 rsurface.tvector3f_bufferobject = 0;
9311 rsurface.tvector3f_bufferoffset = 0;
9312 rsurface.normal3f = rsurface.array_deformednormal3f;
9313 rsurface.normal3f_bufferobject = 0;
9314 rsurface.normal3f_bufferoffset = 0;
9316 case Q3DEFORM_NORMAL:
9317 // deform the normals to make reflections wavey
9318 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9320 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9321 for (j = 0;j < surface->num_vertices;j++)
9324 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9325 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9326 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9327 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9328 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9329 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9330 VectorNormalize(normal);
9332 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);
9334 rsurface.svector3f = rsurface.array_deformedsvector3f;
9335 rsurface.svector3f_bufferobject = 0;
9336 rsurface.svector3f_bufferoffset = 0;
9337 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9338 rsurface.tvector3f_bufferobject = 0;
9339 rsurface.tvector3f_bufferoffset = 0;
9340 rsurface.normal3f = rsurface.array_deformednormal3f;
9341 rsurface.normal3f_bufferobject = 0;
9342 rsurface.normal3f_bufferoffset = 0;
9345 // deform vertex array to make wavey water and flags and such
9346 waveparms[0] = deform->waveparms[0];
9347 waveparms[1] = deform->waveparms[1];
9348 waveparms[2] = deform->waveparms[2];
9349 waveparms[3] = deform->waveparms[3];
9350 // this is how a divisor of vertex influence on deformation
9351 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9352 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9353 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9355 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9356 for (j = 0;j < surface->num_vertices;j++)
9358 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
9359 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
9360 // if the wavefunc depends on time, evaluate it per-vertex
9363 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9364 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9366 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
9369 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9370 rsurface.vertex3f_bufferobject = 0;
9371 rsurface.vertex3f_bufferoffset = 0;
9373 case Q3DEFORM_BULGE:
9374 // deform vertex array to make the surface have moving bulges
9375 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9377 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9378 for (j = 0;j < surface->num_vertices;j++)
9380 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9381 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9384 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9385 rsurface.vertex3f_bufferobject = 0;
9386 rsurface.vertex3f_bufferoffset = 0;
9389 // deform vertex array
9390 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9391 VectorScale(deform->parms, scale, waveparms);
9392 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9394 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9395 for (j = 0;j < surface->num_vertices;j++)
9396 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9398 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9399 rsurface.vertex3f_bufferobject = 0;
9400 rsurface.vertex3f_bufferoffset = 0;
9404 // generate texcoords based on the chosen texcoord source
9405 switch(rsurface.texture->tcgen.tcgen)
9408 case Q3TCGEN_TEXTURE:
9409 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9410 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
9411 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9413 case Q3TCGEN_LIGHTMAP:
9414 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
9415 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9416 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9418 case Q3TCGEN_VECTOR:
9419 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9421 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9422 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)
9424 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9425 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9428 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9429 rsurface.texcoordtexture2f_bufferobject = 0;
9430 rsurface.texcoordtexture2f_bufferoffset = 0;
9432 case Q3TCGEN_ENVIRONMENT:
9433 // make environment reflections using a spheremap
9434 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9436 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9437 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9438 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9439 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9440 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9442 // identical to Q3A's method, but executed in worldspace so
9443 // carried models can be shiny too
9445 float viewer[3], d, reflected[3], worldreflected[3];
9447 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9448 // VectorNormalize(viewer);
9450 d = DotProduct(normal, viewer);
9452 reflected[0] = normal[0]*2*d - viewer[0];
9453 reflected[1] = normal[1]*2*d - viewer[1];
9454 reflected[2] = normal[2]*2*d - viewer[2];
9455 // note: this is proportinal to viewer, so we can normalize later
9457 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9458 VectorNormalize(worldreflected);
9460 // note: this sphere map only uses world x and z!
9461 // so positive and negative y will LOOK THE SAME.
9462 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9463 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9466 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9467 rsurface.texcoordtexture2f_bufferobject = 0;
9468 rsurface.texcoordtexture2f_bufferoffset = 0;
9471 // the only tcmod that needs software vertex processing is turbulent, so
9472 // check for it here and apply the changes if needed
9473 // and we only support that as the first one
9474 // (handling a mixture of turbulent and other tcmods would be problematic
9475 // without punting it entirely to a software path)
9476 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9478 amplitude = rsurface.texture->tcmods[0].parms[1];
9479 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9480 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9482 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9483 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)
9485 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9486 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9489 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9490 rsurface.texcoordtexture2f_bufferobject = 0;
9491 rsurface.texcoordtexture2f_bufferoffset = 0;
9493 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9494 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9495 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9496 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9499 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9502 const msurface_t *surface = texturesurfacelist[0];
9503 const msurface_t *surface2;
9508 // TODO: lock all array ranges before render, rather than on each surface
9509 if (texturenumsurfaces == 1)
9511 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9512 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);
9514 else if (r_batchmode.integer == 2)
9516 #define MAXBATCHTRIANGLES 4096
9517 int batchtriangles = 0;
9518 static int batchelements[MAXBATCHTRIANGLES*3];
9519 for (i = 0;i < texturenumsurfaces;i = j)
9521 surface = texturesurfacelist[i];
9523 if (surface->num_triangles > MAXBATCHTRIANGLES)
9525 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);
9528 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9529 batchtriangles = surface->num_triangles;
9530 firstvertex = surface->num_firstvertex;
9531 endvertex = surface->num_firstvertex + surface->num_vertices;
9532 for (;j < texturenumsurfaces;j++)
9534 surface2 = texturesurfacelist[j];
9535 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9537 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9538 batchtriangles += surface2->num_triangles;
9539 firstvertex = min(firstvertex, surface2->num_firstvertex);
9540 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9542 surface2 = texturesurfacelist[j-1];
9543 numvertices = endvertex - firstvertex;
9544 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9547 else if (r_batchmode.integer == 1)
9549 for (i = 0;i < texturenumsurfaces;i = j)
9551 surface = texturesurfacelist[i];
9552 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9553 if (texturesurfacelist[j] != surface2)
9555 surface2 = texturesurfacelist[j-1];
9556 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9557 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9558 GL_LockArrays(surface->num_firstvertex, numvertices);
9559 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9564 for (i = 0;i < texturenumsurfaces;i++)
9566 surface = texturesurfacelist[i];
9567 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9568 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);
9573 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9575 switch(vid.renderpath)
9577 case RENDERPATH_CGGL:
9579 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9580 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9583 case RENDERPATH_GL20:
9584 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9585 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9587 case RENDERPATH_GL13:
9588 case RENDERPATH_GL11:
9589 R_Mesh_TexBind(0, surface->lightmaptexture);
9594 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9596 // pick the closest matching water plane and bind textures
9597 int planeindex, vertexindex;
9601 r_waterstate_waterplane_t *p, *bestp;
9604 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9607 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9609 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9610 d += fabs(PlaneDiff(vert, &p->plane));
9612 if (bestd > d || !bestp)
9618 switch(vid.renderpath)
9620 case RENDERPATH_CGGL:
9622 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9623 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9626 case RENDERPATH_GL20:
9627 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9628 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9630 case RENDERPATH_GL13:
9631 case RENDERPATH_GL11:
9636 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9639 const msurface_t *surface;
9640 if (r_waterstate.renderingscene)
9642 for (i = 0;i < texturenumsurfaces;i++)
9644 surface = texturesurfacelist[i];
9645 RSurf_BindLightmapForSurface(surface);
9646 RSurf_BindReflectionForSurface(surface);
9647 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9648 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);
9652 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9656 const msurface_t *surface = texturesurfacelist[0];
9657 const msurface_t *surface2;
9662 if (texturenumsurfaces == 1)
9664 RSurf_BindLightmapForSurface(surface);
9665 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9666 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);
9668 else if (r_batchmode.integer == 2)
9670 #define MAXBATCHTRIANGLES 4096
9671 int batchtriangles = 0;
9672 static int batchelements[MAXBATCHTRIANGLES*3];
9673 for (i = 0;i < texturenumsurfaces;i = j)
9675 surface = texturesurfacelist[i];
9676 RSurf_BindLightmapForSurface(surface);
9678 if (surface->num_triangles > MAXBATCHTRIANGLES)
9680 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);
9683 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9684 batchtriangles = surface->num_triangles;
9685 firstvertex = surface->num_firstvertex;
9686 endvertex = surface->num_firstvertex + surface->num_vertices;
9687 for (;j < texturenumsurfaces;j++)
9689 surface2 = texturesurfacelist[j];
9690 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9692 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9693 batchtriangles += surface2->num_triangles;
9694 firstvertex = min(firstvertex, surface2->num_firstvertex);
9695 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9697 surface2 = texturesurfacelist[j-1];
9698 numvertices = endvertex - firstvertex;
9699 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9702 else if (r_batchmode.integer == 1)
9705 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9706 for (i = 0;i < texturenumsurfaces;i = j)
9708 surface = texturesurfacelist[i];
9709 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9710 if (texturesurfacelist[j] != surface2)
9712 Con_Printf(" %i", j - i);
9715 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9717 for (i = 0;i < texturenumsurfaces;i = j)
9719 surface = texturesurfacelist[i];
9720 RSurf_BindLightmapForSurface(surface);
9721 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9722 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9725 Con_Printf(" %i", j - i);
9727 surface2 = texturesurfacelist[j-1];
9728 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9729 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9730 GL_LockArrays(surface->num_firstvertex, numvertices);
9731 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9739 for (i = 0;i < texturenumsurfaces;i++)
9741 surface = texturesurfacelist[i];
9742 RSurf_BindLightmapForSurface(surface);
9743 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9744 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);
9749 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9752 int texturesurfaceindex;
9753 if (r_showsurfaces.integer == 2)
9755 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9757 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9758 for (j = 0;j < surface->num_triangles;j++)
9760 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9761 GL_Color(f, f, f, 1);
9762 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9768 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9770 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9771 int k = (int)(((size_t)surface) / sizeof(msurface_t));
9772 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);
9773 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9774 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);
9779 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9781 int texturesurfaceindex;
9785 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9787 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9788 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)
9796 rsurface.lightmapcolor4f = rsurface.array_color4f;
9797 rsurface.lightmapcolor4f_bufferobject = 0;
9798 rsurface.lightmapcolor4f_bufferoffset = 0;
9801 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9803 int texturesurfaceindex;
9809 if (rsurface.lightmapcolor4f)
9811 // generate color arrays for the surfaces in this list
9812 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9814 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9815 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)
9817 f = RSurf_FogVertex(v);
9827 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9829 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9830 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)
9832 f = RSurf_FogVertex(v);
9840 rsurface.lightmapcolor4f = rsurface.array_color4f;
9841 rsurface.lightmapcolor4f_bufferobject = 0;
9842 rsurface.lightmapcolor4f_bufferoffset = 0;
9845 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9847 int texturesurfaceindex;
9853 if (!rsurface.lightmapcolor4f)
9855 // generate color arrays for the surfaces in this list
9856 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9858 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9859 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)
9861 f = RSurf_FogVertex(v);
9862 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9863 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9864 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9868 rsurface.lightmapcolor4f = rsurface.array_color4f;
9869 rsurface.lightmapcolor4f_bufferobject = 0;
9870 rsurface.lightmapcolor4f_bufferoffset = 0;
9873 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
9875 int texturesurfaceindex;
9879 if (!rsurface.lightmapcolor4f)
9881 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9883 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9884 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)
9892 rsurface.lightmapcolor4f = rsurface.array_color4f;
9893 rsurface.lightmapcolor4f_bufferobject = 0;
9894 rsurface.lightmapcolor4f_bufferoffset = 0;
9897 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9899 int texturesurfaceindex;
9903 if (!rsurface.lightmapcolor4f)
9905 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9907 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9908 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)
9910 c2[0] = c[0] + r_refdef.scene.ambient;
9911 c2[1] = c[1] + r_refdef.scene.ambient;
9912 c2[2] = c[2] + r_refdef.scene.ambient;
9916 rsurface.lightmapcolor4f = rsurface.array_color4f;
9917 rsurface.lightmapcolor4f_bufferobject = 0;
9918 rsurface.lightmapcolor4f_bufferoffset = 0;
9921 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9924 rsurface.lightmapcolor4f = NULL;
9925 rsurface.lightmapcolor4f_bufferobject = 0;
9926 rsurface.lightmapcolor4f_bufferoffset = 0;
9927 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9928 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9929 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9930 GL_Color(r, g, b, a);
9931 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
9934 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9936 // TODO: optimize applyfog && applycolor case
9937 // just apply fog if necessary, and tint the fog color array if necessary
9938 rsurface.lightmapcolor4f = NULL;
9939 rsurface.lightmapcolor4f_bufferobject = 0;
9940 rsurface.lightmapcolor4f_bufferoffset = 0;
9941 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9942 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9943 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9944 GL_Color(r, g, b, a);
9945 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9948 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9950 int texturesurfaceindex;
9954 if (texturesurfacelist[0]->lightmapinfo)
9956 // generate color arrays for the surfaces in this list
9957 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9959 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9960 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
9962 if (surface->lightmapinfo->samples)
9964 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
9965 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
9966 VectorScale(lm, scale, c);
9967 if (surface->lightmapinfo->styles[1] != 255)
9969 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9971 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
9972 VectorMA(c, scale, lm, c);
9973 if (surface->lightmapinfo->styles[2] != 255)
9976 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
9977 VectorMA(c, scale, lm, c);
9978 if (surface->lightmapinfo->styles[3] != 255)
9981 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
9982 VectorMA(c, scale, lm, c);
9992 rsurface.lightmapcolor4f = rsurface.array_color4f;
9993 rsurface.lightmapcolor4f_bufferobject = 0;
9994 rsurface.lightmapcolor4f_bufferoffset = 0;
9998 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
9999 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10000 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10002 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10003 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10004 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10005 GL_Color(r, g, b, a);
10006 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10009 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10011 int texturesurfaceindex;
10018 vec3_t ambientcolor;
10019 vec3_t diffusecolor;
10023 VectorCopy(rsurface.modellight_lightdir, lightdir);
10024 f = 0.5f * r_refdef.lightmapintensity;
10025 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10026 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10027 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10028 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10029 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10030 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10032 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10034 // generate color arrays for the surfaces in this list
10035 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10037 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10038 int numverts = surface->num_vertices;
10039 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10040 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10041 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10042 // q3-style directional shading
10043 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10045 if ((f = DotProduct(n, lightdir)) > 0)
10046 VectorMA(ambientcolor, f, diffusecolor, c);
10048 VectorCopy(ambientcolor, c);
10056 rsurface.lightmapcolor4f = rsurface.array_color4f;
10057 rsurface.lightmapcolor4f_bufferobject = 0;
10058 rsurface.lightmapcolor4f_bufferoffset = 0;
10059 *applycolor = false;
10063 *r = ambientcolor[0];
10064 *g = ambientcolor[1];
10065 *b = ambientcolor[2];
10066 rsurface.lightmapcolor4f = NULL;
10067 rsurface.lightmapcolor4f_bufferobject = 0;
10068 rsurface.lightmapcolor4f_bufferoffset = 0;
10072 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10074 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10075 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10076 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10077 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10078 GL_Color(r, g, b, a);
10079 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10082 void RSurf_SetupDepthAndCulling(void)
10084 // submodels are biased to avoid z-fighting with world surfaces that they
10085 // may be exactly overlapping (avoids z-fighting artifacts on certain
10086 // doors and things in Quake maps)
10087 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10088 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10089 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10090 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10093 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10095 // transparent sky would be ridiculous
10096 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10098 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10099 skyrenderlater = true;
10100 RSurf_SetupDepthAndCulling();
10101 GL_DepthMask(true);
10102 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10103 // skymasking on them, and Quake3 never did sky masking (unlike
10104 // software Quake and software Quake2), so disable the sky masking
10105 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10106 // and skymasking also looks very bad when noclipping outside the
10107 // level, so don't use it then either.
10108 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10110 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10111 R_Mesh_ColorPointer(NULL, 0, 0);
10112 R_Mesh_ResetTextureState();
10113 if (skyrendermasked)
10115 R_SetupShader_DepthOrShadow();
10116 // depth-only (masking)
10117 GL_ColorMask(0,0,0,0);
10118 // just to make sure that braindead drivers don't draw
10119 // anything despite that colormask...
10120 GL_BlendFunc(GL_ZERO, GL_ONE);
10124 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10126 GL_BlendFunc(GL_ONE, GL_ZERO);
10128 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10129 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10130 if (skyrendermasked)
10131 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10133 R_Mesh_ResetTextureState();
10134 GL_Color(1, 1, 1, 1);
10137 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10138 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10139 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10141 qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
10142 qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
10144 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10147 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10148 R_Mesh_ColorPointer(NULL, 0, 0);
10150 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10154 // render background
10155 GL_BlendFunc(GL_ONE, GL_ZERO);
10156 GL_DepthMask(true);
10157 GL_AlphaTest(false);
10159 GL_Color(1, 1, 1, 1);
10160 R_Mesh_ColorPointer(NULL, 0, 0);
10162 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10163 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10164 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10165 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10166 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10167 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10168 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10169 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10170 GL_LockArrays(0, 0);
10172 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10173 GL_DepthMask(false);
10174 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10175 R_Mesh_ColorPointer(NULL, 0, 0);
10177 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10180 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10182 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10183 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10184 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10185 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10186 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10188 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10191 GL_DepthMask(true);
10193 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10194 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10195 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
10197 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10199 if (refract || reflect)
10200 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10202 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10206 if (refract || reflect)
10207 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10209 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10211 GL_LockArrays(0, 0);
10214 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10216 // OpenGL 1.3 path - anything not completely ancient
10217 int texturesurfaceindex;
10218 qboolean applycolor;
10221 const texturelayer_t *layer;
10222 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10224 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10227 int layertexrgbscale;
10228 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10230 if (layerindex == 0)
10231 GL_AlphaTest(true);
10234 GL_AlphaTest(false);
10235 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10238 GL_DepthMask(layer->depthmask && writedepth);
10239 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10240 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10242 layertexrgbscale = 4;
10243 VectorScale(layer->color, 0.25f, layercolor);
10245 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10247 layertexrgbscale = 2;
10248 VectorScale(layer->color, 0.5f, layercolor);
10252 layertexrgbscale = 1;
10253 VectorScale(layer->color, 1.0f, layercolor);
10255 layercolor[3] = layer->color[3];
10256 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10257 R_Mesh_ColorPointer(NULL, 0, 0);
10258 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10259 switch (layer->type)
10261 case TEXTURELAYERTYPE_LITTEXTURE:
10262 // single-pass lightmapped texture with 2x rgbscale
10263 //R_Mesh_TexBind(0, r_texture_white);
10264 R_Mesh_TexMatrix(0, NULL);
10265 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10266 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10267 R_Mesh_TexBind(1, layer->texture);
10268 R_Mesh_TexMatrix(1, &layer->texmatrix);
10269 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10270 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10271 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10272 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10273 else if (rsurface.uselightmaptexture)
10274 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10276 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10278 case TEXTURELAYERTYPE_TEXTURE:
10279 // singletexture unlit texture with transparency support
10280 R_Mesh_TexBind(0, layer->texture);
10281 R_Mesh_TexMatrix(0, &layer->texmatrix);
10282 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10283 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10284 R_Mesh_TexBind(1, 0);
10285 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10286 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10288 case TEXTURELAYERTYPE_FOG:
10289 // singletexture fogging
10290 if (layer->texture)
10292 R_Mesh_TexBind(0, layer->texture);
10293 R_Mesh_TexMatrix(0, &layer->texmatrix);
10294 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10295 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10299 R_Mesh_TexBind(0, 0);
10300 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10302 R_Mesh_TexBind(1, 0);
10303 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10304 // generate a color array for the fog pass
10305 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10306 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10312 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10313 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)
10315 f = 1 - RSurf_FogVertex(v);
10316 c[0] = layercolor[0];
10317 c[1] = layercolor[1];
10318 c[2] = layercolor[2];
10319 c[3] = f * layercolor[3];
10322 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10325 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10327 GL_LockArrays(0, 0);
10330 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10332 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10333 GL_AlphaTest(false);
10337 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10339 // OpenGL 1.1 - crusty old voodoo path
10340 int texturesurfaceindex;
10343 const texturelayer_t *layer;
10344 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10346 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10348 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10350 if (layerindex == 0)
10351 GL_AlphaTest(true);
10354 GL_AlphaTest(false);
10355 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10358 GL_DepthMask(layer->depthmask && writedepth);
10359 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10360 R_Mesh_ColorPointer(NULL, 0, 0);
10361 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10362 switch (layer->type)
10364 case TEXTURELAYERTYPE_LITTEXTURE:
10365 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10367 // two-pass lit texture with 2x rgbscale
10368 // first the lightmap pass
10369 //R_Mesh_TexBind(0, r_texture_white);
10370 R_Mesh_TexMatrix(0, NULL);
10371 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10372 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10373 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10374 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10375 else if (rsurface.uselightmaptexture)
10376 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10378 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10379 GL_LockArrays(0, 0);
10380 // then apply the texture to it
10381 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10382 R_Mesh_TexBind(0, layer->texture);
10383 R_Mesh_TexMatrix(0, &layer->texmatrix);
10384 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10385 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10386 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);
10390 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10391 R_Mesh_TexBind(0, layer->texture);
10392 R_Mesh_TexMatrix(0, &layer->texmatrix);
10393 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10394 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10395 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10396 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);
10398 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);
10401 case TEXTURELAYERTYPE_TEXTURE:
10402 // singletexture unlit texture with transparency support
10403 R_Mesh_TexBind(0, layer->texture);
10404 R_Mesh_TexMatrix(0, &layer->texmatrix);
10405 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10406 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10407 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);
10409 case TEXTURELAYERTYPE_FOG:
10410 // singletexture fogging
10411 if (layer->texture)
10413 R_Mesh_TexBind(0, layer->texture);
10414 R_Mesh_TexMatrix(0, &layer->texmatrix);
10415 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10416 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10420 R_Mesh_TexBind(0, 0);
10421 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10423 // generate a color array for the fog pass
10424 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10425 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10431 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10432 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)
10434 f = 1 - RSurf_FogVertex(v);
10435 c[0] = layer->color[0];
10436 c[1] = layer->color[1];
10437 c[2] = layer->color[2];
10438 c[3] = f * layer->color[3];
10441 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10444 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10446 GL_LockArrays(0, 0);
10449 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10451 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10452 GL_AlphaTest(false);
10456 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10460 GL_AlphaTest(false);
10461 R_Mesh_ColorPointer(NULL, 0, 0);
10462 R_Mesh_ResetTextureState();
10463 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10465 if(rsurface.texture && rsurface.texture->currentskinframe)
10467 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10468 c[3] *= rsurface.texture->currentalpha;
10478 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10480 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10481 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10482 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10485 // brighten it up (as texture value 127 means "unlit")
10486 c[0] *= 2 * r_refdef.view.colorscale;
10487 c[1] *= 2 * r_refdef.view.colorscale;
10488 c[2] *= 2 * r_refdef.view.colorscale;
10490 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10491 c[3] *= r_wateralpha.value;
10493 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10495 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10496 GL_DepthMask(false);
10498 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10500 GL_BlendFunc(GL_ONE, GL_ONE);
10501 GL_DepthMask(false);
10503 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10505 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10506 GL_DepthMask(false);
10508 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10510 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10511 GL_DepthMask(false);
10515 GL_BlendFunc(GL_ONE, GL_ZERO);
10516 GL_DepthMask(writedepth);
10519 rsurface.lightmapcolor4f = NULL;
10521 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10523 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10525 rsurface.lightmapcolor4f = NULL;
10526 rsurface.lightmapcolor4f_bufferobject = 0;
10527 rsurface.lightmapcolor4f_bufferoffset = 0;
10529 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10531 qboolean applycolor = true;
10534 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10536 r_refdef.lightmapintensity = 1;
10537 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10538 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10542 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10544 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10545 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10546 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10549 if(!rsurface.lightmapcolor4f)
10550 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10552 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10553 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10554 if(r_refdef.fogenabled)
10555 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10557 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10558 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10561 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10564 RSurf_SetupDepthAndCulling();
10565 if (r_showsurfaces.integer == 3 && !prepass)
10567 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10570 switch (vid.renderpath)
10572 case RENDERPATH_GL20:
10573 case RENDERPATH_CGGL:
10574 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10576 case RENDERPATH_GL13:
10577 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10579 case RENDERPATH_GL11:
10580 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10586 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10589 RSurf_SetupDepthAndCulling();
10590 if (r_showsurfaces.integer == 3 && !prepass)
10592 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10595 switch (vid.renderpath)
10597 case RENDERPATH_GL20:
10598 case RENDERPATH_CGGL:
10599 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10601 case RENDERPATH_GL13:
10602 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10604 case RENDERPATH_GL11:
10605 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10611 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10614 int texturenumsurfaces, endsurface;
10615 texture_t *texture;
10616 const msurface_t *surface;
10617 const msurface_t *texturesurfacelist[256];
10619 // if the model is static it doesn't matter what value we give for
10620 // wantnormals and wanttangents, so this logic uses only rules applicable
10621 // to a model, knowing that they are meaningless otherwise
10622 if (ent == r_refdef.scene.worldentity)
10623 RSurf_ActiveWorldEntity();
10624 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10625 RSurf_ActiveModelEntity(ent, false, false, false);
10628 switch (vid.renderpath)
10630 case RENDERPATH_GL20:
10631 case RENDERPATH_CGGL:
10632 RSurf_ActiveModelEntity(ent, true, true, false);
10634 case RENDERPATH_GL13:
10635 case RENDERPATH_GL11:
10636 RSurf_ActiveModelEntity(ent, true, false, false);
10641 if (r_transparentdepthmasking.integer)
10643 qboolean setup = false;
10644 for (i = 0;i < numsurfaces;i = j)
10647 surface = rsurface.modelsurfaces + surfacelist[i];
10648 texture = surface->texture;
10649 rsurface.texture = R_GetCurrentTexture(texture);
10650 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10651 // scan ahead until we find a different texture
10652 endsurface = min(i + 1024, numsurfaces);
10653 texturenumsurfaces = 0;
10654 texturesurfacelist[texturenumsurfaces++] = surface;
10655 for (;j < endsurface;j++)
10657 surface = rsurface.modelsurfaces + surfacelist[j];
10658 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10660 texturesurfacelist[texturenumsurfaces++] = surface;
10662 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10664 // render the range of surfaces as depth
10668 GL_ColorMask(0,0,0,0);
10670 GL_DepthTest(true);
10671 GL_BlendFunc(GL_ONE, GL_ZERO);
10672 GL_DepthMask(true);
10673 GL_AlphaTest(false);
10674 R_Mesh_ColorPointer(NULL, 0, 0);
10675 R_Mesh_ResetTextureState();
10676 R_SetupShader_DepthOrShadow();
10678 RSurf_SetupDepthAndCulling();
10679 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10680 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10683 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10686 for (i = 0;i < numsurfaces;i = j)
10689 surface = rsurface.modelsurfaces + surfacelist[i];
10690 texture = surface->texture;
10691 rsurface.texture = R_GetCurrentTexture(texture);
10692 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10693 // scan ahead until we find a different texture
10694 endsurface = min(i + 1024, numsurfaces);
10695 texturenumsurfaces = 0;
10696 texturesurfacelist[texturenumsurfaces++] = surface;
10697 for (;j < endsurface;j++)
10699 surface = rsurface.modelsurfaces + surfacelist[j];
10700 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10702 texturesurfacelist[texturenumsurfaces++] = surface;
10704 // render the range of surfaces
10705 if (ent == r_refdef.scene.worldentity)
10706 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10708 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10710 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10711 GL_AlphaTest(false);
10714 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10716 // transparent surfaces get pushed off into the transparent queue
10717 int surfacelistindex;
10718 const msurface_t *surface;
10719 vec3_t tempcenter, center;
10720 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10722 surface = texturesurfacelist[surfacelistindex];
10723 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10724 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10725 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10726 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10727 if (queueentity->transparent_offset) // transparent offset
10729 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10730 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10731 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10733 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10737 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10739 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10743 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10745 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10747 RSurf_SetupDepthAndCulling();
10748 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10749 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10753 if (!rsurface.texture->currentnumlayers)
10755 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10756 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10758 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10760 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10762 RSurf_SetupDepthAndCulling();
10763 GL_AlphaTest(false);
10764 R_Mesh_ColorPointer(NULL, 0, 0);
10765 R_Mesh_ResetTextureState();
10766 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10767 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10768 GL_DepthMask(true);
10769 GL_BlendFunc(GL_ONE, GL_ZERO);
10770 GL_Color(0, 0, 0, 1);
10771 GL_DepthTest(writedepth);
10772 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10774 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10776 RSurf_SetupDepthAndCulling();
10777 GL_AlphaTest(false);
10778 R_Mesh_ColorPointer(NULL, 0, 0);
10779 R_Mesh_ResetTextureState();
10780 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10781 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10782 GL_DepthMask(true);
10783 GL_BlendFunc(GL_ONE, GL_ZERO);
10784 GL_DepthTest(true);
10785 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10787 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10788 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10789 else if (!rsurface.texture->currentnumlayers)
10791 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10793 // in the deferred case, transparent surfaces were queued during prepass
10794 if (!r_shadow_usingdeferredprepass)
10795 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10799 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10800 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10805 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10808 texture_t *texture;
10809 // break the surface list down into batches by texture and use of lightmapping
10810 for (i = 0;i < numsurfaces;i = j)
10813 // texture is the base texture pointer, rsurface.texture is the
10814 // current frame/skin the texture is directing us to use (for example
10815 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10816 // use skin 1 instead)
10817 texture = surfacelist[i]->texture;
10818 rsurface.texture = R_GetCurrentTexture(texture);
10819 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10820 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10822 // if this texture is not the kind we want, skip ahead to the next one
10823 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10827 // simply scan ahead until we find a different texture or lightmap state
10828 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10830 // render the range of surfaces
10831 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10835 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10840 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10842 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10844 RSurf_SetupDepthAndCulling();
10845 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10846 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10850 if (!rsurface.texture->currentnumlayers)
10852 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10853 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10855 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10857 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10859 RSurf_SetupDepthAndCulling();
10860 GL_AlphaTest(false);
10861 R_Mesh_ColorPointer(NULL, 0, 0);
10862 R_Mesh_ResetTextureState();
10863 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10864 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10865 GL_DepthMask(true);
10866 GL_BlendFunc(GL_ONE, GL_ZERO);
10867 GL_Color(0, 0, 0, 1);
10868 GL_DepthTest(writedepth);
10869 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10871 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10873 RSurf_SetupDepthAndCulling();
10874 GL_AlphaTest(false);
10875 R_Mesh_ColorPointer(NULL, 0, 0);
10876 R_Mesh_ResetTextureState();
10877 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10878 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10879 GL_DepthMask(true);
10880 GL_BlendFunc(GL_ONE, GL_ZERO);
10881 GL_DepthTest(true);
10882 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10884 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10885 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10886 else if (!rsurface.texture->currentnumlayers)
10888 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10890 // in the deferred case, transparent surfaces were queued during prepass
10891 if (!r_shadow_usingdeferredprepass)
10892 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10896 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10897 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10902 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10905 texture_t *texture;
10906 // break the surface list down into batches by texture and use of lightmapping
10907 for (i = 0;i < numsurfaces;i = j)
10910 // texture is the base texture pointer, rsurface.texture is the
10911 // current frame/skin the texture is directing us to use (for example
10912 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10913 // use skin 1 instead)
10914 texture = surfacelist[i]->texture;
10915 rsurface.texture = R_GetCurrentTexture(texture);
10916 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10917 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10919 // if this texture is not the kind we want, skip ahead to the next one
10920 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10924 // simply scan ahead until we find a different texture or lightmap state
10925 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10927 // render the range of surfaces
10928 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10932 float locboxvertex3f[6*4*3] =
10934 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10935 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10936 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10937 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10938 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10939 1,0,0, 0,0,0, 0,1,0, 1,1,0
10942 unsigned short locboxelements[6*2*3] =
10947 12,13,14, 12,14,15,
10948 16,17,18, 16,18,19,
10952 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10955 cl_locnode_t *loc = (cl_locnode_t *)ent;
10957 float vertex3f[6*4*3];
10959 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10960 GL_DepthMask(false);
10961 GL_DepthRange(0, 1);
10962 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10963 GL_DepthTest(true);
10964 GL_CullFace(GL_NONE);
10965 R_EntityMatrix(&identitymatrix);
10967 R_Mesh_VertexPointer(vertex3f, 0, 0);
10968 R_Mesh_ColorPointer(NULL, 0, 0);
10969 R_Mesh_ResetTextureState();
10970 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10972 i = surfacelist[0];
10973 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10974 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10975 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10976 surfacelist[0] < 0 ? 0.5f : 0.125f);
10978 if (VectorCompare(loc->mins, loc->maxs))
10980 VectorSet(size, 2, 2, 2);
10981 VectorMA(loc->mins, -0.5f, size, mins);
10985 VectorCopy(loc->mins, mins);
10986 VectorSubtract(loc->maxs, loc->mins, size);
10989 for (i = 0;i < 6*4*3;)
10990 for (j = 0;j < 3;j++, i++)
10991 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10993 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
10996 void R_DrawLocs(void)
10999 cl_locnode_t *loc, *nearestloc;
11001 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11002 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11004 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11005 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11009 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11011 if (decalsystem->decals)
11012 Mem_Free(decalsystem->decals);
11013 memset(decalsystem, 0, sizeof(*decalsystem));
11016 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)
11019 tridecal_t *decals;
11023 // expand or initialize the system
11024 if (decalsystem->maxdecals <= decalsystem->numdecals)
11026 decalsystem_t old = *decalsystem;
11027 qboolean useshortelements;
11028 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11029 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11030 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)));
11031 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11032 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11033 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11034 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11035 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11036 if (decalsystem->numdecals)
11037 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11039 Mem_Free(old.decals);
11040 for (i = 0;i < decalsystem->maxdecals*3;i++)
11041 decalsystem->element3i[i] = i;
11042 if (useshortelements)
11043 for (i = 0;i < decalsystem->maxdecals*3;i++)
11044 decalsystem->element3s[i] = i;
11047 // grab a decal and search for another free slot for the next one
11048 maxdecals = decalsystem->maxdecals;
11049 decals = decalsystem->decals;
11050 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11051 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11053 decalsystem->freedecal = i;
11054 if (decalsystem->numdecals <= i)
11055 decalsystem->numdecals = i + 1;
11057 // initialize the decal
11059 decal->triangleindex = triangleindex;
11060 decal->surfaceindex = surfaceindex;
11061 decal->decalsequence = decalsequence;
11062 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11063 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11064 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11065 decal->color4ub[0][3] = 255;
11066 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11067 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11068 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11069 decal->color4ub[1][3] = 255;
11070 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11071 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11072 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11073 decal->color4ub[2][3] = 255;
11074 decal->vertex3f[0][0] = v0[0];
11075 decal->vertex3f[0][1] = v0[1];
11076 decal->vertex3f[0][2] = v0[2];
11077 decal->vertex3f[1][0] = v1[0];
11078 decal->vertex3f[1][1] = v1[1];
11079 decal->vertex3f[1][2] = v1[2];
11080 decal->vertex3f[2][0] = v2[0];
11081 decal->vertex3f[2][1] = v2[1];
11082 decal->vertex3f[2][2] = v2[2];
11083 decal->texcoord2f[0][0] = t0[0];
11084 decal->texcoord2f[0][1] = t0[1];
11085 decal->texcoord2f[1][0] = t1[0];
11086 decal->texcoord2f[1][1] = t1[1];
11087 decal->texcoord2f[2][0] = t2[0];
11088 decal->texcoord2f[2][1] = t2[1];
11091 extern cvar_t cl_decals_bias;
11092 extern cvar_t cl_decals_models;
11093 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11094 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)
11096 matrix4x4_t projection;
11097 decalsystem_t *decalsystem;
11100 const float *vertex3f;
11101 const msurface_t *surface;
11102 const msurface_t *surfaces;
11103 const int *surfacelist;
11104 const texture_t *texture;
11107 int numsurfacelist;
11108 int surfacelistindex;
11111 int decalsurfaceindex;
11116 float localorigin[3];
11117 float localnormal[3];
11118 float localmins[3];
11119 float localmaxs[3];
11126 float planes[6][4];
11128 float points[2][9][3];
11132 decalsystem = &ent->decalsystem;
11133 model = ent->model;
11134 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11136 R_DecalSystem_Reset(&ent->decalsystem);
11140 if (!model->brush.data_nodes && !cl_decals_models.integer)
11142 if (decalsystem->model)
11143 R_DecalSystem_Reset(decalsystem);
11147 if (decalsystem->model != model)
11148 R_DecalSystem_Reset(decalsystem);
11149 decalsystem->model = model;
11151 RSurf_ActiveModelEntity(ent, false, false, false);
11153 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11154 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11155 VectorNormalize(localnormal);
11156 localsize = worldsize*rsurface.inversematrixscale;
11157 ilocalsize = 1.0f / localsize;
11158 localmins[0] = localorigin[0] - localsize;
11159 localmins[1] = localorigin[1] - localsize;
11160 localmins[2] = localorigin[2] - localsize;
11161 localmaxs[0] = localorigin[0] + localsize;
11162 localmaxs[1] = localorigin[1] + localsize;
11163 localmaxs[2] = localorigin[2] + localsize;
11165 //VectorCopy(localnormal, planes[4]);
11166 //VectorVectors(planes[4], planes[2], planes[0]);
11167 AnglesFromVectors(angles, localnormal, NULL, false);
11168 AngleVectors(angles, planes[0], planes[2], planes[4]);
11169 VectorNegate(planes[0], planes[1]);
11170 VectorNegate(planes[2], planes[3]);
11171 VectorNegate(planes[4], planes[5]);
11172 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11173 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11174 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11175 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11176 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11177 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11182 matrix4x4_t forwardprojection;
11183 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11184 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11189 float projectionvector[4][3];
11190 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11191 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11192 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11193 projectionvector[0][0] = planes[0][0] * ilocalsize;
11194 projectionvector[0][1] = planes[1][0] * ilocalsize;
11195 projectionvector[0][2] = planes[2][0] * ilocalsize;
11196 projectionvector[1][0] = planes[0][1] * ilocalsize;
11197 projectionvector[1][1] = planes[1][1] * ilocalsize;
11198 projectionvector[1][2] = planes[2][1] * ilocalsize;
11199 projectionvector[2][0] = planes[0][2] * ilocalsize;
11200 projectionvector[2][1] = planes[1][2] * ilocalsize;
11201 projectionvector[2][2] = planes[2][2] * ilocalsize;
11202 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11203 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11204 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11205 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11209 dynamic = model->surfmesh.isanimated;
11210 vertex3f = rsurface.modelvertex3f;
11211 numsurfacelist = model->nummodelsurfaces;
11212 surfacelist = model->sortedmodelsurfaces;
11213 surfaces = model->data_surfaces;
11214 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11216 surfaceindex = surfacelist[surfacelistindex];
11217 surface = surfaces + surfaceindex;
11218 // skip transparent surfaces
11219 texture = surface->texture;
11220 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11222 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11224 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11226 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11227 numvertices = surface->num_vertices;
11228 numtriangles = surface->num_triangles;
11229 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11231 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11233 index = 3*e[cornerindex];
11234 VectorCopy(vertex3f + index, v[cornerindex]);
11237 //TriangleNormal(v[0], v[1], v[2], normal);
11238 //if (DotProduct(normal, localnormal) < 0.0f)
11240 // clip by each of the box planes formed from the projection matrix
11241 // if anything survives, we emit the decal
11242 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]);
11245 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]);
11248 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]);
11251 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]);
11254 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]);
11257 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]);
11260 // some part of the triangle survived, so we have to accept it...
11263 // dynamic always uses the original triangle
11265 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11267 index = 3*e[cornerindex];
11268 VectorCopy(vertex3f + index, v[cornerindex]);
11271 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11273 // convert vertex positions to texcoords
11274 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11275 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11276 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11277 // calculate distance fade from the projection origin
11278 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11279 f = bound(0.0f, f, 1.0f);
11280 c[cornerindex][0] = r * f;
11281 c[cornerindex][1] = g * f;
11282 c[cornerindex][2] = b * f;
11283 c[cornerindex][3] = 1.0f;
11284 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11287 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);
11289 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11290 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);
11295 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11296 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)
11298 int renderentityindex;
11299 float worldmins[3];
11300 float worldmaxs[3];
11301 entity_render_t *ent;
11303 if (!cl_decals_newsystem.integer)
11306 worldmins[0] = worldorigin[0] - worldsize;
11307 worldmins[1] = worldorigin[1] - worldsize;
11308 worldmins[2] = worldorigin[2] - worldsize;
11309 worldmaxs[0] = worldorigin[0] + worldsize;
11310 worldmaxs[1] = worldorigin[1] + worldsize;
11311 worldmaxs[2] = worldorigin[2] + worldsize;
11313 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11315 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11317 ent = r_refdef.scene.entities[renderentityindex];
11318 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11321 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11325 typedef struct r_decalsystem_splatqueue_s
11327 vec3_t worldorigin;
11328 vec3_t worldnormal;
11334 r_decalsystem_splatqueue_t;
11336 int r_decalsystem_numqueued = 0;
11337 #define MAX_DECALSYSTEM_QUEUE 1024
11338 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11340 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)
11342 r_decalsystem_splatqueue_t *queue;
11344 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11347 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11348 VectorCopy(worldorigin, queue->worldorigin);
11349 VectorCopy(worldnormal, queue->worldnormal);
11350 Vector4Set(queue->color, r, g, b, a);
11351 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11352 queue->worldsize = worldsize;
11353 queue->decalsequence = cl.decalsequence++;
11356 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11359 r_decalsystem_splatqueue_t *queue;
11361 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11362 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);
11363 r_decalsystem_numqueued = 0;
11366 extern cvar_t cl_decals_max;
11367 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11370 decalsystem_t *decalsystem = &ent->decalsystem;
11377 if (!decalsystem->numdecals)
11380 if (r_showsurfaces.integer)
11383 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11385 R_DecalSystem_Reset(decalsystem);
11389 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11390 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11392 if (decalsystem->lastupdatetime)
11393 frametime = (cl.time - decalsystem->lastupdatetime);
11396 decalsystem->lastupdatetime = cl.time;
11397 decal = decalsystem->decals;
11398 numdecals = decalsystem->numdecals;
11400 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11402 if (decal->color4ub[0][3])
11404 decal->lived += frametime;
11405 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11407 memset(decal, 0, sizeof(*decal));
11408 if (decalsystem->freedecal > i)
11409 decalsystem->freedecal = i;
11413 decal = decalsystem->decals;
11414 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11417 // collapse the array by shuffling the tail decals into the gaps
11420 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11421 decalsystem->freedecal++;
11422 if (decalsystem->freedecal == numdecals)
11424 decal[decalsystem->freedecal] = decal[--numdecals];
11427 decalsystem->numdecals = numdecals;
11429 if (numdecals <= 0)
11431 // if there are no decals left, reset decalsystem
11432 R_DecalSystem_Reset(decalsystem);
11436 extern skinframe_t *decalskinframe;
11437 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11440 decalsystem_t *decalsystem = &ent->decalsystem;
11450 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11453 numdecals = decalsystem->numdecals;
11457 if (r_showsurfaces.integer)
11460 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11462 R_DecalSystem_Reset(decalsystem);
11466 // if the model is static it doesn't matter what value we give for
11467 // wantnormals and wanttangents, so this logic uses only rules applicable
11468 // to a model, knowing that they are meaningless otherwise
11469 if (ent == r_refdef.scene.worldentity)
11470 RSurf_ActiveWorldEntity();
11472 RSurf_ActiveModelEntity(ent, false, false, false);
11474 decalsystem->lastupdatetime = cl.time;
11475 decal = decalsystem->decals;
11477 fadedelay = cl_decals_time.value;
11478 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11480 // update vertex positions for animated models
11481 v3f = decalsystem->vertex3f;
11482 c4f = decalsystem->color4f;
11483 t2f = decalsystem->texcoord2f;
11484 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11486 if (!decal->color4ub[0][3])
11489 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11492 // update color values for fading decals
11493 if (decal->lived >= cl_decals_time.value)
11495 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11496 alpha *= (1.0f/255.0f);
11499 alpha = 1.0f/255.0f;
11501 c4f[ 0] = decal->color4ub[0][0] * alpha;
11502 c4f[ 1] = decal->color4ub[0][1] * alpha;
11503 c4f[ 2] = decal->color4ub[0][2] * alpha;
11505 c4f[ 4] = decal->color4ub[1][0] * alpha;
11506 c4f[ 5] = decal->color4ub[1][1] * alpha;
11507 c4f[ 6] = decal->color4ub[1][2] * alpha;
11509 c4f[ 8] = decal->color4ub[2][0] * alpha;
11510 c4f[ 9] = decal->color4ub[2][1] * alpha;
11511 c4f[10] = decal->color4ub[2][2] * alpha;
11514 t2f[0] = decal->texcoord2f[0][0];
11515 t2f[1] = decal->texcoord2f[0][1];
11516 t2f[2] = decal->texcoord2f[1][0];
11517 t2f[3] = decal->texcoord2f[1][1];
11518 t2f[4] = decal->texcoord2f[2][0];
11519 t2f[5] = decal->texcoord2f[2][1];
11521 // update vertex positions for animated models
11522 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11524 e = rsurface.modelelement3i + 3*decal->triangleindex;
11525 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11526 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11527 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11531 VectorCopy(decal->vertex3f[0], v3f);
11532 VectorCopy(decal->vertex3f[1], v3f + 3);
11533 VectorCopy(decal->vertex3f[2], v3f + 6);
11544 r_refdef.stats.drawndecals += numtris;
11546 if (r_refdef.fogenabled)
11548 switch(vid.renderpath)
11550 case RENDERPATH_GL20:
11551 case RENDERPATH_CGGL:
11552 case RENDERPATH_GL13:
11553 case RENDERPATH_GL11:
11554 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11556 alpha = RSurf_FogVertex(v3f);
11565 // now render the decals all at once
11566 // (this assumes they all use one particle font texture!)
11567 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);
11568 R_Mesh_ResetTextureState();
11569 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11570 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11571 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11572 GL_DepthMask(false);
11573 GL_DepthRange(0, 1);
11574 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11575 GL_DepthTest(true);
11576 GL_CullFace(GL_NONE);
11577 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11578 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11579 GL_LockArrays(0, numtris * 3);
11580 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11581 GL_LockArrays(0, 0);
11585 static void R_DrawModelDecals(void)
11589 // fade faster when there are too many decals
11590 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11591 for (i = 0;i < r_refdef.scene.numentities;i++)
11592 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11594 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11595 for (i = 0;i < r_refdef.scene.numentities;i++)
11596 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11597 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11599 R_DecalSystem_ApplySplatEntitiesQueue();
11601 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11602 for (i = 0;i < r_refdef.scene.numentities;i++)
11603 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11605 r_refdef.stats.totaldecals += numdecals;
11607 if (r_showsurfaces.integer)
11610 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11612 for (i = 0;i < r_refdef.scene.numentities;i++)
11614 if (!r_refdef.viewcache.entityvisible[i])
11616 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11617 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11621 void R_DrawDebugModel(void)
11623 entity_render_t *ent = rsurface.entity;
11624 int i, j, k, l, flagsmask;
11625 const int *elements;
11627 const msurface_t *surface;
11628 dp_model_t *model = ent->model;
11631 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11633 R_Mesh_ColorPointer(NULL, 0, 0);
11634 R_Mesh_ResetTextureState();
11635 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11636 GL_DepthRange(0, 1);
11637 GL_DepthTest(!r_showdisabledepthtest.integer);
11638 GL_DepthMask(false);
11639 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11641 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11643 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11644 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11646 if (brush->colbrushf && brush->colbrushf->numtriangles)
11648 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11649 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);
11650 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11653 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11655 if (surface->num_collisiontriangles)
11657 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11658 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);
11659 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11664 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11666 if (r_showtris.integer || r_shownormals.integer)
11668 if (r_showdisabledepthtest.integer)
11670 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11671 GL_DepthMask(false);
11675 GL_BlendFunc(GL_ONE, GL_ZERO);
11676 GL_DepthMask(true);
11678 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11680 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11682 rsurface.texture = R_GetCurrentTexture(surface->texture);
11683 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11685 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11686 if (r_showtris.value > 0)
11688 if (!rsurface.texture->currentlayers->depthmask)
11689 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11690 else if (ent == r_refdef.scene.worldentity)
11691 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11693 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11694 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11695 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11696 R_Mesh_ColorPointer(NULL, 0, 0);
11697 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11698 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11699 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11700 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);
11701 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11704 if (r_shownormals.value < 0)
11706 qglBegin(GL_LINES);
11707 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11709 VectorCopy(rsurface.vertex3f + l * 3, v);
11710 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11711 qglVertex3f(v[0], v[1], v[2]);
11712 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11713 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11714 qglVertex3f(v[0], v[1], v[2]);
11719 if (r_shownormals.value > 0)
11721 qglBegin(GL_LINES);
11722 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11724 VectorCopy(rsurface.vertex3f + l * 3, v);
11725 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11726 qglVertex3f(v[0], v[1], v[2]);
11727 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11728 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11729 qglVertex3f(v[0], v[1], v[2]);
11733 qglBegin(GL_LINES);
11734 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11736 VectorCopy(rsurface.vertex3f + l * 3, v);
11737 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11738 qglVertex3f(v[0], v[1], v[2]);
11739 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11740 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11741 qglVertex3f(v[0], v[1], v[2]);
11745 qglBegin(GL_LINES);
11746 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11748 VectorCopy(rsurface.vertex3f + l * 3, v);
11749 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11750 qglVertex3f(v[0], v[1], v[2]);
11751 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11752 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11753 qglVertex3f(v[0], v[1], v[2]);
11760 rsurface.texture = NULL;
11764 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11765 int r_maxsurfacelist = 0;
11766 const msurface_t **r_surfacelist = NULL;
11767 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11769 int i, j, endj, f, flagsmask;
11771 dp_model_t *model = r_refdef.scene.worldmodel;
11772 msurface_t *surfaces;
11773 unsigned char *update;
11774 int numsurfacelist = 0;
11778 if (r_maxsurfacelist < model->num_surfaces)
11780 r_maxsurfacelist = model->num_surfaces;
11782 Mem_Free((msurface_t**)r_surfacelist);
11783 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11786 RSurf_ActiveWorldEntity();
11788 surfaces = model->data_surfaces;
11789 update = model->brushq1.lightmapupdateflags;
11791 // update light styles on this submodel
11792 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11794 model_brush_lightstyleinfo_t *style;
11795 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11797 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11799 int *list = style->surfacelist;
11800 style->value = r_refdef.scene.lightstylevalue[style->style];
11801 for (j = 0;j < style->numsurfaces;j++)
11802 update[list[j]] = true;
11807 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11811 R_DrawDebugModel();
11812 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11818 rsurface.uselightmaptexture = false;
11819 rsurface.texture = NULL;
11820 rsurface.rtlight = NULL;
11821 numsurfacelist = 0;
11822 // add visible surfaces to draw list
11823 for (i = 0;i < model->nummodelsurfaces;i++)
11825 j = model->sortedmodelsurfaces[i];
11826 if (r_refdef.viewcache.world_surfacevisible[j])
11827 r_surfacelist[numsurfacelist++] = surfaces + j;
11829 // update lightmaps if needed
11830 if (model->brushq1.firstrender)
11832 model->brushq1.firstrender = false;
11833 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11835 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11839 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11840 if (r_refdef.viewcache.world_surfacevisible[j])
11842 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11844 // don't do anything if there were no surfaces
11845 if (!numsurfacelist)
11847 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11850 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11851 GL_AlphaTest(false);
11853 // add to stats if desired
11854 if (r_speeds.integer && !skysurfaces && !depthonly)
11856 r_refdef.stats.world_surfaces += numsurfacelist;
11857 for (j = 0;j < numsurfacelist;j++)
11858 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11861 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11864 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11866 int i, j, endj, f, flagsmask;
11868 dp_model_t *model = ent->model;
11869 msurface_t *surfaces;
11870 unsigned char *update;
11871 int numsurfacelist = 0;
11875 if (r_maxsurfacelist < model->num_surfaces)
11877 r_maxsurfacelist = model->num_surfaces;
11879 Mem_Free((msurface_t **)r_surfacelist);
11880 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11883 // if the model is static it doesn't matter what value we give for
11884 // wantnormals and wanttangents, so this logic uses only rules applicable
11885 // to a model, knowing that they are meaningless otherwise
11886 if (ent == r_refdef.scene.worldentity)
11887 RSurf_ActiveWorldEntity();
11888 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11889 RSurf_ActiveModelEntity(ent, false, false, false);
11891 RSurf_ActiveModelEntity(ent, true, true, true);
11892 else if (depthonly)
11893 RSurf_ActiveModelEntity(ent, false, false, false);
11896 switch (vid.renderpath)
11898 case RENDERPATH_GL20:
11899 case RENDERPATH_CGGL:
11900 RSurf_ActiveModelEntity(ent, true, true, false);
11902 case RENDERPATH_GL13:
11903 case RENDERPATH_GL11:
11904 RSurf_ActiveModelEntity(ent, true, false, false);
11909 surfaces = model->data_surfaces;
11910 update = model->brushq1.lightmapupdateflags;
11912 // update light styles
11913 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11915 model_brush_lightstyleinfo_t *style;
11916 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11918 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11920 int *list = style->surfacelist;
11921 style->value = r_refdef.scene.lightstylevalue[style->style];
11922 for (j = 0;j < style->numsurfaces;j++)
11923 update[list[j]] = true;
11928 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11932 R_DrawDebugModel();
11933 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11939 rsurface.uselightmaptexture = false;
11940 rsurface.texture = NULL;
11941 rsurface.rtlight = NULL;
11942 numsurfacelist = 0;
11943 // add visible surfaces to draw list
11944 for (i = 0;i < model->nummodelsurfaces;i++)
11945 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11946 // don't do anything if there were no surfaces
11947 if (!numsurfacelist)
11949 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11952 // update lightmaps if needed
11956 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11961 R_BuildLightMap(ent, surfaces + j);
11966 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11968 R_BuildLightMap(ent, surfaces + j);
11969 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11970 GL_AlphaTest(false);
11972 // add to stats if desired
11973 if (r_speeds.integer && !skysurfaces && !depthonly)
11975 r_refdef.stats.entities_surfaces += numsurfacelist;
11976 for (j = 0;j < numsurfacelist;j++)
11977 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11980 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11983 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11985 static texture_t texture;
11986 static msurface_t surface;
11987 const msurface_t *surfacelist = &surface;
11989 // fake enough texture and surface state to render this geometry
11991 texture.update_lastrenderframe = -1; // regenerate this texture
11992 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11993 texture.currentskinframe = skinframe;
11994 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11995 texture.specularscalemod = 1;
11996 texture.specularpowermod = 1;
11998 surface.texture = &texture;
11999 surface.num_triangles = numtriangles;
12000 surface.num_firsttriangle = firsttriangle;
12001 surface.num_vertices = numvertices;
12002 surface.num_firstvertex = firstvertex;
12005 rsurface.texture = R_GetCurrentTexture(surface.texture);
12006 rsurface.uselightmaptexture = false;
12007 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12010 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)
12012 static msurface_t surface;
12013 const msurface_t *surfacelist = &surface;
12015 // fake enough texture and surface state to render this geometry
12017 surface.texture = texture;
12018 surface.num_triangles = numtriangles;
12019 surface.num_firsttriangle = firsttriangle;
12020 surface.num_vertices = numvertices;
12021 surface.num_firstvertex = firstvertex;
12024 rsurface.texture = R_GetCurrentTexture(surface.texture);
12025 rsurface.uselightmaptexture = false;
12026 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);