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_textureframe = 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 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
844 "varying vec3 LightVector;\n"
847 "#ifdef USEEYEVECTOR\n"
848 "varying vec3 EyeVector;\n"
851 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
854 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
855 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
856 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
857 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
860 "#ifdef USEREFLECTION\n"
861 "varying vec4 ModelViewProjectionPosition;\n"
863 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
864 "uniform vec3 LightPosition;\n"
865 "varying vec4 ModelViewPosition;\n"
868 "#ifdef MODE_LIGHTSOURCE\n"
869 "uniform vec3 LightPosition;\n"
871 "uniform vec3 EyePosition;\n"
872 "#ifdef MODE_LIGHTDIRECTION\n"
873 "uniform vec3 LightDir;\n"
875 "uniform vec4 FogPlane;\n"
881 "// 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"
883 "// fragment shader specific:\n"
884 "#ifdef FRAGMENT_SHADER\n"
886 "uniform sampler2D Texture_Normal;\n"
887 "uniform sampler2D Texture_Color;\n"
888 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
889 "uniform sampler2D Texture_Gloss;\n"
892 "uniform sampler2D Texture_Glow;\n"
894 "#ifdef USEVERTEXTEXTUREBLEND\n"
895 "uniform sampler2D Texture_SecondaryNormal;\n"
896 "uniform sampler2D Texture_SecondaryColor;\n"
897 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
898 "uniform sampler2D Texture_SecondaryGloss;\n"
901 "uniform sampler2D Texture_SecondaryGlow;\n"
904 "#ifdef USECOLORMAPPING\n"
905 "uniform sampler2D Texture_Pants;\n"
906 "uniform sampler2D Texture_Shirt;\n"
909 "uniform sampler2D Texture_FogMask;\n"
911 "#ifdef USELIGHTMAP\n"
912 "uniform sampler2D Texture_Lightmap;\n"
914 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
915 "uniform sampler2D Texture_Deluxemap;\n"
917 "#ifdef USEREFLECTION\n"
918 "uniform sampler2D Texture_Reflection;\n"
921 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
922 "uniform sampler2D Texture_ScreenDepth;\n"
923 "uniform sampler2D Texture_ScreenNormalMap;\n"
925 "#ifdef USEDEFERREDLIGHTMAP\n"
926 "uniform sampler2D Texture_ScreenDiffuse;\n"
927 "uniform sampler2D Texture_ScreenSpecular;\n"
930 "uniform myhalf3 Color_Pants;\n"
931 "uniform myhalf3 Color_Shirt;\n"
932 "uniform myhalf3 FogColor;\n"
935 "uniform float FogRangeRecip;\n"
936 "uniform float FogPlaneViewDist;\n"
937 "uniform float FogHeightFade;\n"
938 "float FogVertex(void)\n"
940 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
941 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
943 "#ifdef USEFOGOUTSIDE\n"
944 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
946 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
948 " return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
952 "#ifdef USEOFFSETMAPPING\n"
953 "uniform float OffsetMapping_Scale;\n"
954 "vec2 OffsetMapping(vec2 TexCoord)\n"
956 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
957 " // 14 sample relief mapping: linear search and then binary search\n"
958 " // this basically steps forward a small amount repeatedly until it finds\n"
959 " // itself inside solid, then jitters forward and back using decreasing\n"
960 " // amounts to find the impact\n"
961 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
962 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
963 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
964 " vec3 RT = vec3(TexCoord, 1);\n"
965 " OffsetVector *= 0.1;\n"
966 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
967 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
968 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
969 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
970 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
971 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
972 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
973 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
976 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
977 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
978 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
979 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
982 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
983 " // this basically moves forward the full distance, and then backs up based\n"
984 " // on height of samples\n"
985 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
986 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
987 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
988 " TexCoord += OffsetVector;\n"
989 " OffsetVector *= 0.333;\n"
990 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
991 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
992 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
993 " return TexCoord;\n"
996 "#endif // USEOFFSETMAPPING\n"
998 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
999 "uniform sampler2D Texture_Attenuation;\n"
1000 "uniform samplerCube Texture_Cube;\n"
1002 "#ifdef USESHADOWMAPRECT\n"
1003 "# ifdef USESHADOWSAMPLER\n"
1004 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1006 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1010 "#ifdef USESHADOWMAP2D\n"
1011 "# ifdef USESHADOWSAMPLER\n"
1012 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1014 "uniform sampler2D Texture_ShadowMap2D;\n"
1018 "#ifdef USESHADOWMAPVSDCT\n"
1019 "uniform samplerCube Texture_CubeProjection;\n"
1022 "#ifdef USESHADOWMAPCUBE\n"
1023 "# ifdef USESHADOWSAMPLER\n"
1024 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1026 "uniform samplerCube Texture_ShadowMapCube;\n"
1030 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1031 "uniform vec2 ShadowMap_TextureScale;\n"
1032 "uniform vec4 ShadowMap_Parameters;\n"
1035 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1036 "# ifndef USESHADOWMAPVSDCT\n"
1037 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1039 " vec3 adir = abs(dir);\n"
1043 " if (adir.x > adir.y)\n"
1045 " if (adir.x > adir.z) // X\n"
1049 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1055 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1060 " if (adir.y > adir.z) // Y\n"
1064 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1070 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1074 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1075 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1076 " stc.z += ShadowMap_Parameters.z;\n"
1080 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1082 " vec3 adir = abs(dir);\n"
1083 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1084 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1085 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1086 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1087 " stc.z += ShadowMap_Parameters.z;\n"
1091 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1093 "#ifdef USESHADOWMAPCUBE\n"
1094 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1096 " vec3 adir = abs(dir);\n"
1097 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1101 "# ifdef USESHADOWMAPRECT\n"
1102 "float ShadowMapCompare(vec3 dir)\n"
1104 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1106 "# ifdef USESHADOWSAMPLER\n"
1108 "# ifdef USESHADOWMAPPCF\n"
1109 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1110 " 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"
1112 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1117 "# ifdef USESHADOWMAPPCF\n"
1118 "# if USESHADOWMAPPCF > 1\n"
1119 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1120 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1121 " 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"
1122 " 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"
1123 " 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"
1124 " 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"
1125 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1126 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1128 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1129 " vec2 offset = fract(shadowmaptc.xy);\n"
1130 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1131 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1132 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1133 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1134 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1137 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1145 "# ifdef USESHADOWMAP2D\n"
1146 "float ShadowMapCompare(vec3 dir)\n"
1148 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1151 "# ifdef USESHADOWSAMPLER\n"
1152 "# ifdef USESHADOWMAPPCF\n"
1153 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1154 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1155 " 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"
1157 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1160 "# ifdef USESHADOWMAPPCF\n"
1161 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1162 "# ifdef GL_ARB_texture_gather\n"
1163 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1165 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1167 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1168 " center *= ShadowMap_TextureScale;\n"
1169 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1170 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1171 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1172 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1173 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1174 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1175 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1177 "# ifdef GL_EXT_gpu_shader4\n"
1178 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1180 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1182 "# if USESHADOWMAPPCF > 1\n"
1183 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1184 " center *= ShadowMap_TextureScale;\n"
1185 " 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"
1186 " 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"
1187 " 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"
1188 " 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"
1189 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1190 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1192 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1193 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1194 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1195 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1196 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1197 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1201 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1208 "# ifdef USESHADOWMAPCUBE\n"
1209 "float ShadowMapCompare(vec3 dir)\n"
1211 " // apply depth texture cubemap as light filter\n"
1212 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1214 "# ifdef USESHADOWSAMPLER\n"
1215 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1217 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1222 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1223 "#endif // FRAGMENT_SHADER\n"
1228 "#ifdef MODE_DEFERREDGEOMETRY\n"
1229 "#ifdef VERTEX_SHADER\n"
1230 "uniform mat4 TexMatrix;\n"
1231 "#ifdef USEVERTEXTEXTUREBLEND\n"
1232 "uniform mat4 BackgroundTexMatrix;\n"
1234 "uniform mat4 ModelViewMatrix;\n"
1237 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1238 "#ifdef USEVERTEXTEXTUREBLEND\n"
1239 " gl_FrontColor = gl_Color;\n"
1240 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1243 " // transform unnormalized eye direction into tangent space\n"
1244 "#ifdef USEOFFSETMAPPING\n"
1245 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1246 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1247 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1248 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1251 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1252 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1253 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1254 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1256 "#endif // VERTEX_SHADER\n"
1258 "#ifdef FRAGMENT_SHADER\n"
1261 "#ifdef USEOFFSETMAPPING\n"
1262 " // apply offsetmapping\n"
1263 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1264 "#define TexCoord TexCoordOffset\n"
1267 "#ifdef USEALPHAKILL\n"
1268 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1272 "#ifdef USEVERTEXTEXTUREBLEND\n"
1273 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1274 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1275 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1276 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1279 "#ifdef USEVERTEXTEXTUREBLEND\n"
1280 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1282 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1285 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1287 "#endif // FRAGMENT_SHADER\n"
1288 "#else // !MODE_DEFERREDGEOMETRY\n"
1293 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1294 "#ifdef VERTEX_SHADER\n"
1295 "uniform mat4 ModelViewMatrix;\n"
1298 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1299 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1301 "#endif // VERTEX_SHADER\n"
1303 "#ifdef FRAGMENT_SHADER\n"
1304 "uniform mat4 ViewToLight;\n"
1305 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1306 "uniform vec2 ScreenToDepth;\n"
1307 "uniform myhalf3 DeferredColor_Ambient;\n"
1308 "uniform myhalf3 DeferredColor_Diffuse;\n"
1309 "#ifdef USESPECULAR\n"
1310 "uniform myhalf3 DeferredColor_Specular;\n"
1311 "uniform myhalf SpecularPower;\n"
1313 "uniform myhalf2 PixelToScreenTexCoord;\n"
1316 " // calculate viewspace pixel position\n"
1317 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1319 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1320 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1321 " // decode viewspace pixel normal\n"
1322 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1323 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1324 " // surfacenormal = pixel normal in viewspace\n"
1325 " // LightVector = pixel to light in viewspace\n"
1326 " // CubeVector = position in lightspace\n"
1327 " // eyevector = pixel to view in viewspace\n"
1328 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1329 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1330 "#ifdef USEDIFFUSE\n"
1331 " // calculate diffuse shading\n"
1332 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1333 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1335 "#ifdef USESPECULAR\n"
1336 " // calculate directional shading\n"
1337 " vec3 eyevector = position * -1.0;\n"
1338 "# ifdef USEEXACTSPECULARMATH\n"
1339 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1341 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1342 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1346 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1347 " fade *= ShadowMapCompare(CubeVector);\n"
1350 "#ifdef USEDIFFUSE\n"
1351 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1353 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1355 "#ifdef USESPECULAR\n"
1356 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1358 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1361 "# ifdef USECUBEFILTER\n"
1362 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1363 " gl_FragData[0].rgb *= cubecolor;\n"
1364 " gl_FragData[1].rgb *= cubecolor;\n"
1367 "#endif // FRAGMENT_SHADER\n"
1368 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1373 "#ifdef VERTEX_SHADER\n"
1374 "uniform mat4 TexMatrix;\n"
1375 "#ifdef USEVERTEXTEXTUREBLEND\n"
1376 "uniform mat4 BackgroundTexMatrix;\n"
1378 "#ifdef MODE_LIGHTSOURCE\n"
1379 "uniform mat4 ModelToLight;\n"
1383 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1384 " gl_FrontColor = gl_Color;\n"
1386 " // copy the surface texcoord\n"
1387 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1388 "#ifdef USEVERTEXTEXTUREBLEND\n"
1389 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1391 "#ifdef USELIGHTMAP\n"
1392 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1395 "#ifdef MODE_LIGHTSOURCE\n"
1396 " // transform vertex position into light attenuation/cubemap space\n"
1397 " // (-1 to +1 across the light box)\n"
1398 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1400 "# ifdef USEDIFFUSE\n"
1401 " // transform unnormalized light direction into tangent space\n"
1402 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1403 " // normalize it per pixel)\n"
1404 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1405 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1406 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1407 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1411 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1412 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1413 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1414 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1417 " // transform unnormalized eye direction into tangent space\n"
1418 "#ifdef USEEYEVECTOR\n"
1419 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1420 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1421 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1422 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1426 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1427 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1430 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1431 " VectorS = gl_MultiTexCoord1.xyz;\n"
1432 " VectorT = gl_MultiTexCoord2.xyz;\n"
1433 " VectorR = gl_MultiTexCoord3.xyz;\n"
1436 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1437 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1439 "#ifdef USEREFLECTION\n"
1440 " ModelViewProjectionPosition = gl_Position;\n"
1443 "#endif // VERTEX_SHADER\n"
1448 "#ifdef FRAGMENT_SHADER\n"
1449 "#ifdef USEDEFERREDLIGHTMAP\n"
1450 "uniform myhalf2 PixelToScreenTexCoord;\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 "#ifdef USEDIFFUSE\n"
1524 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1525 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1526 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1527 "#ifdef USESPECULAR\n"
1528 "#ifdef USEEXACTSPECULARMATH\n"
1529 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1531 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1532 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1534 " color.rgb += glosstex * (specular * Color_Specular);\n"
1537 " color.rgb = diffusetex * Color_Ambient;\n"
1539 " color.rgb *= LightColor;\n"
1540 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1541 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1542 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1544 "# ifdef USECUBEFILTER\n"
1545 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1547 "#endif // MODE_LIGHTSOURCE\n"
1552 "#ifdef MODE_LIGHTDIRECTION\n"
1554 "#ifdef USEDIFFUSE\n"
1555 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1557 "#define lightcolor LightColor\n"
1558 "#endif // MODE_LIGHTDIRECTION\n"
1559 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1561 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1562 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1563 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1564 " // convert modelspace light vector to tangentspace\n"
1565 " myhalf3 lightnormal;\n"
1566 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1567 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1568 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1569 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1570 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1571 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1572 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1573 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1574 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1575 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1576 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1577 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1578 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1579 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1580 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1582 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1583 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1584 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1590 "#ifdef MODE_LIGHTMAP\n"
1591 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1592 "#endif // MODE_LIGHTMAP\n"
1593 "#ifdef MODE_VERTEXCOLOR\n"
1594 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1595 "#endif // MODE_VERTEXCOLOR\n"
1596 "#ifdef MODE_FLATCOLOR\n"
1597 " color.rgb = diffusetex * Color_Ambient;\n"
1598 "#endif // MODE_FLATCOLOR\n"
1604 "# ifdef USEDIFFUSE\n"
1605 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1606 "# ifdef USESPECULAR\n"
1607 "# ifdef USEEXACTSPECULARMATH\n"
1608 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1610 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1611 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1613 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1615 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1618 " color.rgb = diffusetex * Color_Ambient;\n"
1622 "#ifdef USEDEFERREDLIGHTMAP\n"
1623 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1624 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1625 " color.rgb += glosstex * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1629 "#ifdef USEVERTEXTEXTUREBLEND\n"
1630 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1632 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1637 "#ifdef MODE_LIGHTSOURCE\n"
1638 " color.rgb *= myhalf(FogVertex());\n"
1640 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1644 " // 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"
1645 "#ifdef USEREFLECTION\n"
1646 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1647 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1648 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1649 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1650 " // FIXME temporary hack to detect the case that the reflection\n"
1651 " // gets blackened at edges due to leaving the area that contains actual\n"
1653 " // Remove this 'ack once we have a better way to stop this thing from\n"
1655 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1656 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1657 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1658 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1659 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1660 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1663 " gl_FragColor = vec4(color);\n"
1665 "#endif // FRAGMENT_SHADER\n"
1667 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1668 "#endif // !MODE_DEFERREDGEOMETRY\n"
1669 "#endif // !MODE_WATER\n"
1670 "#endif // !MODE_REFRACTION\n"
1671 "#endif // !MODE_BLOOMBLUR\n"
1672 "#endif // !MODE_GENERIC\n"
1673 "#endif // !MODE_POSTPROCESS\n"
1674 "#endif // !MODE_SHOWDEPTH\n"
1675 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1679 =========================================================================================================================================================
1683 =========================================================================================================================================================
1687 =========================================================================================================================================================
1691 =========================================================================================================================================================
1695 =========================================================================================================================================================
1699 =========================================================================================================================================================
1703 =========================================================================================================================================================
1706 const char *builtincgshaderstring =
1707 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1708 "// written by Forest 'LordHavoc' Hale\n"
1709 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1711 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1714 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1715 "#define USELIGHTMAP\n"
1717 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1718 "#define USEEYEVECTOR\n"
1721 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1722 "#ifdef VERTEX_SHADER\n"
1725 "float4 gl_Vertex : POSITION,\n"
1726 "uniform float4x4 ModelViewProjectionMatrix,\n"
1727 "out float4 gl_Position : POSITION\n"
1730 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1733 "#else // !MODE_DEPTH_ORSHADOW\n"
1738 "#ifdef MODE_SHOWDEPTH\n"
1739 "#ifdef VERTEX_SHADER\n"
1742 "float4 gl_Vertex : POSITION,\n"
1743 "uniform float4x4 ModelViewProjectionMatrix,\n"
1744 "out float4 gl_Position : POSITION,\n"
1745 "out float4 gl_FrontColor : COLOR0\n"
1748 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1749 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1753 "#ifdef FRAGMENT_SHADER\n"
1756 "float4 gl_FrontColor : COLOR0,\n"
1757 "out float4 gl_FragColor : COLOR\n"
1760 " gl_FragColor = gl_FrontColor;\n"
1763 "#else // !MODE_SHOWDEPTH\n"
1768 "#ifdef MODE_POSTPROCESS\n"
1770 "#ifdef VERTEX_SHADER\n"
1773 "float4 gl_Vertex : POSITION,\n"
1774 "uniform float4x4 ModelViewProjectionMatrix,\n"
1775 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1776 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1777 "out float4 gl_Position : POSITION,\n"
1778 "out float2 TexCoord1 : TEXCOORD0,\n"
1779 "out float2 TexCoord2 : TEXCOORD1\n"
1782 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1783 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1785 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1790 "#ifdef FRAGMENT_SHADER\n"
1793 "float2 TexCoord1 : TEXCOORD0,\n"
1794 "float2 TexCoord2 : TEXCOORD1,\n"
1795 "uniform sampler2D Texture_First,\n"
1797 "uniform sampler2D Texture_Second,\n"
1799 "#ifdef USEGAMMARAMPS\n"
1800 "uniform sampler2D Texture_GammaRamps,\n"
1802 "#ifdef USESATURATION\n"
1803 "uniform float Saturation,\n"
1805 "#ifdef USEVIEWTINT\n"
1806 "uniform float4 ViewTintColor,\n"
1808 "uniform float4 UserVec1,\n"
1809 "uniform float4 UserVec2,\n"
1810 "uniform float4 UserVec3,\n"
1811 "uniform float4 UserVec4,\n"
1812 "uniform float ClientTime,\n"
1813 "uniform float2 PixelSize,\n"
1814 "out float4 gl_FragColor : COLOR\n"
1817 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1819 " gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1821 "#ifdef USEVIEWTINT\n"
1822 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1825 "#ifdef USEPOSTPROCESSING\n"
1826 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1827 "// 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"
1828 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1829 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1830 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1831 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
1832 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
1833 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1836 "#ifdef USESATURATION\n"
1837 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1838 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1839 " //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1840 " gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1843 "#ifdef USEGAMMARAMPS\n"
1844 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1845 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1846 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1850 "#else // !MODE_POSTPROCESS\n"
1855 "#ifdef MODE_GENERIC\n"
1856 "#ifdef VERTEX_SHADER\n"
1859 "float4 gl_Vertex : POSITION,\n"
1860 "uniform float4x4 ModelViewProjectionMatrix,\n"
1861 "float4 gl_Color : COLOR0,\n"
1862 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1863 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1864 "out float4 gl_Position : POSITION,\n"
1865 "out float4 gl_FrontColor : COLOR,\n"
1866 "out float2 TexCoord1 : TEXCOORD0,\n"
1867 "out float2 TexCoord2 : TEXCOORD1\n"
1870 " gl_FrontColor = gl_Color;\n"
1871 "#ifdef USEDIFFUSE\n"
1872 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1874 "#ifdef USESPECULAR\n"
1875 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1877 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1881 "#ifdef FRAGMENT_SHADER\n"
1885 "float4 gl_FrontColor : COLOR,\n"
1886 "float2 TexCoord1 : TEXCOORD0,\n"
1887 "float2 TexCoord2 : TEXCOORD1,\n"
1888 "#ifdef USEDIFFUSE\n"
1889 "uniform sampler2D Texture_First,\n"
1891 "#ifdef USESPECULAR\n"
1892 "uniform sampler2D Texture_Second,\n"
1894 "out float4 gl_FragColor : COLOR\n"
1897 " gl_FragColor = gl_FrontColor;\n"
1898 "#ifdef USEDIFFUSE\n"
1899 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1902 "#ifdef USESPECULAR\n"
1903 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1904 "# ifdef USECOLORMAPPING\n"
1905 " gl_FragColor *= tex2;\n"
1908 " gl_FragColor += tex2;\n"
1910 "# ifdef USEVERTEXTEXTUREBLEND\n"
1911 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1916 "#else // !MODE_GENERIC\n"
1921 "#ifdef MODE_BLOOMBLUR\n"
1922 "#ifdef VERTEX_SHADER\n"
1925 "float4 gl_Vertex : POSITION,\n"
1926 "uniform float4x4 ModelViewProjectionMatrix,\n"
1927 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1928 "out float4 gl_Position : POSITION,\n"
1929 "out float2 TexCoord : TEXCOORD0\n"
1932 " TexCoord = gl_MultiTexCoord0.xy;\n"
1933 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1937 "#ifdef FRAGMENT_SHADER\n"
1941 "float2 TexCoord : TEXCOORD0,\n"
1942 "uniform sampler2D Texture_First,\n"
1943 "uniform float4 BloomBlur_Parameters,\n"
1944 "out float4 gl_FragColor : COLOR\n"
1948 " float2 tc = TexCoord;\n"
1949 " float3 color = tex2D(Texture_First, tc).rgb;\n"
1950 " tc += BloomBlur_Parameters.xy;\n"
1951 " for (i = 1;i < SAMPLES;i++)\n"
1953 " color += tex2D(Texture_First, tc).rgb;\n"
1954 " tc += BloomBlur_Parameters.xy;\n"
1956 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1959 "#else // !MODE_BLOOMBLUR\n"
1960 "#ifdef MODE_REFRACTION\n"
1961 "#ifdef VERTEX_SHADER\n"
1964 "float4 gl_Vertex : POSITION,\n"
1965 "uniform float4x4 ModelViewProjectionMatrix,\n"
1966 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1967 "uniform float4x4 TexMatrix,\n"
1968 "uniform float3 EyePosition,\n"
1969 "out float4 gl_Position : POSITION,\n"
1970 "out float2 TexCoord : TEXCOORD0,\n"
1971 "out float3 EyeVector : TEXCOORD1,\n"
1972 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1975 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1976 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1977 " ModelViewProjectionPosition = gl_Position;\n"
1981 "#ifdef FRAGMENT_SHADER\n"
1984 "float2 TexCoord : TEXCOORD0,\n"
1985 "float3 EyeVector : TEXCOORD1,\n"
1986 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1987 "uniform sampler2D Texture_Normal,\n"
1988 "uniform sampler2D Texture_Refraction,\n"
1989 "uniform sampler2D Texture_Reflection,\n"
1990 "uniform float4 DistortScaleRefractReflect,\n"
1991 "uniform float4 ScreenScaleRefractReflect,\n"
1992 "uniform float4 ScreenCenterRefractReflect,\n"
1993 "uniform float4 RefractColor,\n"
1994 "out float4 gl_FragColor : COLOR\n"
1997 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1998 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1999 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2000 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2001 " // FIXME temporary hack to detect the case that the reflection\n"
2002 " // gets blackened at edges due to leaving the area that contains actual\n"
2004 " // Remove this 'ack once we have a better way to stop this thing from\n"
2006 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2007 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2008 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2009 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2010 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2011 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2014 "#else // !MODE_REFRACTION\n"
2019 "#ifdef MODE_WATER\n"
2020 "#ifdef VERTEX_SHADER\n"
2024 "float4 gl_Vertex : POSITION,\n"
2025 "uniform float4x4 ModelViewProjectionMatrix,\n"
2026 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2027 "uniform float4x4 TexMatrix,\n"
2028 "uniform float3 EyePosition,\n"
2029 "out float4 gl_Position : POSITION,\n"
2030 "out float2 TexCoord : TEXCOORD0,\n"
2031 "out float3 EyeVector : TEXCOORD1,\n"
2032 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2035 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2036 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2037 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2038 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2039 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2040 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2041 " ModelViewProjectionPosition = gl_Position;\n"
2045 "#ifdef FRAGMENT_SHADER\n"
2048 "float2 TexCoord : TEXCOORD0,\n"
2049 "float3 EyeVector : TEXCOORD1,\n"
2050 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2051 "uniform sampler2D Texture_Normal,\n"
2052 "uniform sampler2D Texture_Refraction,\n"
2053 "uniform sampler2D Texture_Reflection,\n"
2054 "uniform float4 DistortScaleRefractReflect,\n"
2055 "uniform float4 ScreenScaleRefractReflect,\n"
2056 "uniform float4 ScreenCenterRefractReflect,\n"
2057 "uniform float4 RefractColor,\n"
2058 "uniform float4 ReflectColor,\n"
2059 "uniform float ReflectFactor,\n"
2060 "uniform float ReflectOffset,\n"
2061 "out float4 gl_FragColor : COLOR\n"
2064 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2065 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2066 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2067 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2068 " // FIXME temporary hack to detect the case that the reflection\n"
2069 " // gets blackened at edges due to leaving the area that contains actual\n"
2071 " // Remove this 'ack once we have a better way to stop this thing from\n"
2073 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2074 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2075 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2076 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2077 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2078 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2079 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2080 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2081 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2082 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2083 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2084 " gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2087 "#else // !MODE_WATER\n"
2092 "// 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"
2094 "// fragment shader specific:\n"
2095 "#ifdef FRAGMENT_SHADER\n"
2098 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2101 "#ifdef USEFOGOUTSIDE\n"
2102 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2104 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2106 " return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2110 "#ifdef USEOFFSETMAPPING\n"
2111 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2113 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2114 " // 14 sample relief mapping: linear search and then binary search\n"
2115 " // this basically steps forward a small amount repeatedly until it finds\n"
2116 " // itself inside solid, then jitters forward and back using decreasing\n"
2117 " // amounts to find the impact\n"
2118 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2119 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2120 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2121 " float3 RT = float3(TexCoord, 1);\n"
2122 " OffsetVector *= 0.1;\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);\n"
2128 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2129 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2130 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2131 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2132 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2133 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2134 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2135 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2136 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2139 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2140 " // this basically moves forward the full distance, and then backs up based\n"
2141 " // on height of samples\n"
2142 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2143 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2144 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2145 " TexCoord += OffsetVector;\n"
2146 " OffsetVector *= 0.333;\n"
2147 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2148 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2149 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2150 " return TexCoord;\n"
2153 "#endif // USEOFFSETMAPPING\n"
2155 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2156 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2157 "# ifndef USESHADOWMAPVSDCT\n"
2158 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2160 " float3 adir = abs(dir);\n"
2164 " if (adir.x > adir.y)\n"
2166 " if (adir.x > adir.z) // X\n"
2170 " offset = float2(lerp(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2176 " offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2181 " if (adir.y > adir.z) // Y\n"
2185 " offset = float2(lerp(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2191 " offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2195 " float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2196 " stc.xy += offset * ShadowMap_Parameters.y;\n"
2197 " stc.z += ShadowMap_Parameters.z;\n"
2201 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2203 " float3 adir = abs(dir);\n"
2204 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2205 " float ma = max(max(adir.x, adir.y), adir.z);\n"
2206 " float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2207 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2208 " stc.z += ShadowMap_Parameters.z;\n"
2212 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2214 "#ifdef USESHADOWMAPCUBE\n"
2215 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2217 " float3 adir = abs(dir);\n"
2218 " return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2222 "# ifdef USESHADOWMAPRECT\n"
2223 "#ifdef USESHADOWMAPVSDCT\n"
2224 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2226 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2229 "#ifdef USESHADOWMAPVSDCT\n"
2230 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2232 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2235 "# ifdef USESHADOWSAMPLER\n"
2237 "# ifdef USESHADOWMAPPCF\n"
2238 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2239 " 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"
2241 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2246 "# ifdef USESHADOWMAPPCF\n"
2247 "# if USESHADOWMAPPCF > 1\n"
2248 "# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2249 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2250 " 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"
2251 " 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"
2252 " 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"
2253 " 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"
2254 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2255 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2257 "# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2258 " float2 offset = frac(shadowmaptc.xy);\n"
2259 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2260 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2261 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2262 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2263 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2266 " f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2274 "# ifdef USESHADOWMAP2D\n"
2275 "#ifdef USESHADOWMAPVSDCT\n"
2276 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2278 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2281 "#ifdef USESHADOWMAPVSDCT\n"
2282 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2284 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2288 "# ifdef USESHADOWSAMPLER\n"
2289 "# ifdef USESHADOWMAPPCF\n"
2290 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
2291 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2292 " 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"
2294 " f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2297 "# ifdef USESHADOWMAPPCF\n"
2298 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2299 "# ifdef GL_ARB_texture_gather\n"
2300 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2302 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2304 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2305 " center *= ShadowMap_TextureScale;\n"
2306 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2307 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2308 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2309 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2310 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2311 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2312 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2314 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale) \n"
2315 "# if USESHADOWMAPPCF > 1\n"
2316 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2317 " center *= ShadowMap_TextureScale;\n"
2318 " 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"
2319 " 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"
2320 " 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"
2321 " 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"
2322 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2323 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2325 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2326 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2327 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2328 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2329 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2330 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2334 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2341 "# ifdef USESHADOWMAPCUBE\n"
2342 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2344 " // apply depth texture cubemap as light filter\n"
2345 " float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2347 "# ifdef USESHADOWSAMPLER\n"
2348 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2350 " f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2355 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2356 "#endif // FRAGMENT_SHADER\n"
2361 "#ifdef MODE_DEFERREDGEOMETRY\n"
2362 "#ifdef VERTEX_SHADER\n"
2365 "float4 gl_Vertex : POSITION,\n"
2366 "uniform float4x4 ModelViewProjectionMatrix,\n"
2367 "#ifdef USEVERTEXTEXTUREBLEND\n"
2368 "float4 gl_Color : COLOR0,\n"
2370 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2371 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2372 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2373 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2374 "uniform float4x4 TexMatrix,\n"
2375 "#ifdef USEVERTEXTEXTUREBLEND\n"
2376 "uniform float4x4 BackgroundTexMatrix,\n"
2378 "uniform float4x4 ModelViewMatrix,\n"
2379 "#ifdef USEOFFSETMAPPING\n"
2380 "uniform float3 EyePosition,\n"
2382 "out float4 gl_Position : POSITION,\n"
2383 "out float4 gl_FrontColor : COLOR,\n"
2384 "out float4 TexCoordBoth : TEXCOORD0,\n"
2385 "#ifdef USEOFFSETMAPPING\n"
2386 "out float3 EyeVector : TEXCOORD2,\n"
2388 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2389 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2390 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2393 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2394 "#ifdef USEVERTEXTEXTUREBLEND\n"
2395 " gl_FrontColor = gl_Color;\n"
2396 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2399 " // transform unnormalized eye direction into tangent space\n"
2400 "#ifdef USEOFFSETMAPPING\n"
2401 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2402 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2403 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2404 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2407 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2408 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2409 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2410 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2412 "#endif // VERTEX_SHADER\n"
2414 "#ifdef FRAGMENT_SHADER\n"
2417 "float4 TexCoordBoth : TEXCOORD0,\n"
2418 "float3 EyeVector : TEXCOORD2,\n"
2419 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2420 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2421 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2422 "uniform sampler2D Texture_Normal,\n"
2423 "#ifdef USEALPHAKILL\n"
2424 "uniform sampler2D Texture_Color,\n"
2426 "#ifdef USEVERTEXTEXTUREBLEND\n"
2427 "uniform sampler2D Texture_SecondaryNormal,\n"
2429 "#ifdef USEOFFSETMAPPING\n"
2430 "uniform float OffsetMapping_Scale,\n"
2432 "uniform half SpecularPower,\n"
2433 "out float4 gl_FragColor : COLOR\n"
2436 " float2 TexCoord = TexCoordBoth.xy;\n"
2437 "#ifdef USEOFFSETMAPPING\n"
2438 " // apply offsetmapping\n"
2439 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2440 "#define TexCoord TexCoordOffset\n"
2443 "#ifdef USEALPHAKILL\n"
2444 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2448 "#ifdef USEVERTEXTEXTUREBLEND\n"
2449 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2450 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2451 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2452 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2455 "#ifdef USEVERTEXTEXTUREBLEND\n"
2456 " float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2458 " float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2461 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2463 "#endif // FRAGMENT_SHADER\n"
2464 "#else // !MODE_DEFERREDGEOMETRY\n"
2469 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2470 "#ifdef VERTEX_SHADER\n"
2473 "float4 gl_Vertex : POSITION,\n"
2474 "uniform float4x4 ModelViewProjectionMatrix,\n"
2475 "uniform float4x4 ModelViewMatrix,\n"
2476 "out float4 gl_Position : POSITION,\n"
2477 "out float4 ModelViewPosition : TEXCOORD0\n"
2480 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2481 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2483 "#endif // VERTEX_SHADER\n"
2485 "#ifdef FRAGMENT_SHADER\n"
2488 "float2 Pixel : WPOS,\n"
2489 "float4 ModelViewPosition : TEXCOORD0,\n"
2490 "uniform float4x4 ViewToLight,\n"
2491 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2492 "uniform float3 LightPosition,\n"
2493 "uniform half2 PixelToScreenTexCoord,\n"
2494 "uniform half3 DeferredColor_Ambient,\n"
2495 "uniform half3 DeferredColor_Diffuse,\n"
2496 "#ifdef USESPECULAR\n"
2497 "uniform half3 DeferredColor_Specular,\n"
2498 "uniform half SpecularPower,\n"
2500 "uniform sampler2D Texture_Attenuation,\n"
2501 "uniform sampler2D Texture_ScreenDepth,\n"
2502 "uniform sampler2D Texture_ScreenNormalMap,\n"
2504 "#ifdef USESHADOWMAPRECT\n"
2505 "# ifdef USESHADOWSAMPLER\n"
2506 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2508 "uniform samplerRECT Texture_ShadowMapRect,\n"
2512 "#ifdef USESHADOWMAP2D\n"
2513 "# ifdef USESHADOWSAMPLER\n"
2514 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2516 "uniform sampler2D Texture_ShadowMap2D,\n"
2520 "#ifdef USESHADOWMAPVSDCT\n"
2521 "uniform samplerCUBE Texture_CubeProjection,\n"
2524 "#ifdef USESHADOWMAPCUBE\n"
2525 "# ifdef USESHADOWSAMPLER\n"
2526 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2528 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2532 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2533 "uniform float2 ShadowMap_TextureScale,\n"
2534 "uniform float4 ShadowMap_Parameters,\n"
2537 "out float4 gl_FragData0 : COLOR0,\n"
2538 "out float4 gl_FragData1 : COLOR1\n"
2541 " // calculate viewspace pixel position\n"
2542 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2543 " ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2544 " float3 position;\n"
2545 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2546 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2547 " // decode viewspace pixel normal\n"
2548 " half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2549 " half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2550 " // surfacenormal = pixel normal in viewspace\n"
2551 " // LightVector = pixel to light in viewspace\n"
2552 " // CubeVector = position in lightspace\n"
2553 " // eyevector = pixel to view in viewspace\n"
2554 " float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2555 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2556 "#ifdef USEDIFFUSE\n"
2557 " // calculate diffuse shading\n"
2558 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2559 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2561 "#ifdef USESPECULAR\n"
2562 " // calculate directional shading\n"
2563 " float3 eyevector = position * -1.0;\n"
2564 "# ifdef USEEXACTSPECULARMATH\n"
2565 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2567 " half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2568 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2572 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2573 " fade *= ShadowMapCompare(CubeVector,\n"
2574 "# if defined(USESHADOWMAP2D)\n"
2575 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2577 "# if defined(USESHADOWMAPRECT)\n"
2578 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2580 "# if defined(USESHADOWMAPCUBE)\n"
2581 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2584 "#ifdef USESHADOWMAPVSDCT\n"
2585 ", Texture_CubeProjection\n"
2590 "#ifdef USEDIFFUSE\n"
2591 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2593 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2595 "#ifdef USESPECULAR\n"
2596 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2598 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2601 "# ifdef USECUBEFILTER\n"
2602 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2603 " gl_FragData0.rgb *= cubecolor;\n"
2604 " gl_FragData1.rgb *= cubecolor;\n"
2607 "#endif // FRAGMENT_SHADER\n"
2608 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2613 "#ifdef VERTEX_SHADER\n"
2616 "float4 gl_Vertex : POSITION,\n"
2617 "uniform float4x4 ModelViewProjectionMatrix,\n"
2618 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2619 "float4 gl_Color : COLOR0,\n"
2621 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2622 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2623 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2624 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2625 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2627 "uniform float3 EyePosition,\n"
2628 "uniform float4x4 TexMatrix,\n"
2629 "#ifdef USEVERTEXTEXTUREBLEND\n"
2630 "uniform float4x4 BackgroundTexMatrix,\n"
2632 "#ifdef MODE_LIGHTSOURCE\n"
2633 "uniform float4x4 ModelToLight,\n"
2635 "#ifdef MODE_LIGHTSOURCE\n"
2636 "uniform float3 LightPosition,\n"
2638 "#ifdef MODE_LIGHTDIRECTION\n"
2639 "uniform float3 LightDir,\n"
2641 "uniform float4 FogPlane,\n"
2642 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2643 "uniform float3 LightPosition,\n"
2646 "out float4 gl_FrontColor : COLOR,\n"
2647 "out float4 TexCoordBoth : TEXCOORD0,\n"
2648 "#ifdef USELIGHTMAP\n"
2649 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2651 "#ifdef USEEYEVECTOR\n"
2652 "out float3 EyeVector : TEXCOORD2,\n"
2654 "#ifdef USEREFLECTION\n"
2655 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2658 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2660 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2661 "out float3 LightVector : TEXCOORD5,\n"
2663 "#ifdef MODE_LIGHTSOURCE\n"
2664 "out float3 CubeVector : TEXCOORD3,\n"
2666 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2667 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2668 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2669 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2671 "out float4 gl_Position : POSITION\n"
2674 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2675 " gl_FrontColor = gl_Color;\n"
2677 " // copy the surface texcoord\n"
2678 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2679 "#ifdef USEVERTEXTEXTUREBLEND\n"
2680 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2682 "#ifdef USELIGHTMAP\n"
2683 " TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2686 "#ifdef MODE_LIGHTSOURCE\n"
2687 " // transform vertex position into light attenuation/cubemap space\n"
2688 " // (-1 to +1 across the light box)\n"
2689 " CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2691 "# ifdef USEDIFFUSE\n"
2692 " // transform unnormalized light direction into tangent space\n"
2693 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2694 " // normalize it per pixel)\n"
2695 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2696 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2697 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2698 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2702 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2703 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2704 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2705 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2708 " // transform unnormalized eye direction into tangent space\n"
2709 "#ifdef USEEYEVECTOR\n"
2710 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2711 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2712 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2713 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2717 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2718 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2721 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2722 " VectorS = gl_MultiTexCoord1.xyz;\n"
2723 " VectorT = gl_MultiTexCoord2.xyz;\n"
2724 " VectorR = gl_MultiTexCoord3.xyz;\n"
2727 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2728 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2730 "#ifdef USEREFLECTION\n"
2731 " ModelViewProjectionPosition = gl_Position;\n"
2734 "#endif // VERTEX_SHADER\n"
2739 "#ifdef FRAGMENT_SHADER\n"
2742 "#ifdef USEDEFERREDLIGHTMAP\n"
2743 "float2 Pixel : WPOS,\n"
2745 "float4 gl_FrontColor : COLOR,\n"
2746 "float4 TexCoordBoth : TEXCOORD0,\n"
2747 "#ifdef USELIGHTMAP\n"
2748 "float2 TexCoordLightmap : TEXCOORD1,\n"
2750 "#ifdef USEEYEVECTOR\n"
2751 "float3 EyeVector : TEXCOORD2,\n"
2753 "#ifdef USEREFLECTION\n"
2754 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2757 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2759 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2760 "float3 LightVector : TEXCOORD5,\n"
2762 "#ifdef MODE_LIGHTSOURCE\n"
2763 "float3 CubeVector : TEXCOORD3,\n"
2765 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2766 "float4 ModelViewPosition : TEXCOORD0,\n"
2768 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2769 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2770 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2771 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2774 "uniform sampler2D Texture_Normal,\n"
2775 "uniform sampler2D Texture_Color,\n"
2776 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2777 "uniform sampler2D Texture_Gloss,\n"
2780 "uniform sampler2D Texture_Glow,\n"
2782 "#ifdef USEVERTEXTEXTUREBLEND\n"
2783 "uniform sampler2D Texture_SecondaryNormal,\n"
2784 "uniform sampler2D Texture_SecondaryColor,\n"
2785 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2786 "uniform sampler2D Texture_SecondaryGloss,\n"
2789 "uniform sampler2D Texture_SecondaryGlow,\n"
2792 "#ifdef USECOLORMAPPING\n"
2793 "uniform sampler2D Texture_Pants,\n"
2794 "uniform sampler2D Texture_Shirt,\n"
2797 "uniform sampler2D Texture_FogMask,\n"
2799 "#ifdef USELIGHTMAP\n"
2800 "uniform sampler2D Texture_Lightmap,\n"
2802 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2803 "uniform sampler2D Texture_Deluxemap,\n"
2805 "#ifdef USEREFLECTION\n"
2806 "uniform sampler2D Texture_Reflection,\n"
2809 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2810 "uniform sampler2D Texture_ScreenDepth,\n"
2811 "uniform sampler2D Texture_ScreenNormalMap,\n"
2813 "#ifdef USEDEFERREDLIGHTMAP\n"
2814 "uniform sampler2D Texture_ScreenDiffuse,\n"
2815 "uniform sampler2D Texture_ScreenSpecular,\n"
2818 "#ifdef USECOLORMAPPING\n"
2819 "uniform half3 Color_Pants,\n"
2820 "uniform half3 Color_Shirt,\n"
2823 "uniform float3 FogColor,\n"
2824 "uniform float FogRangeRecip,\n"
2825 "uniform float FogPlaneViewDist,\n"
2826 "uniform float FogHeightFade,\n"
2829 "#ifdef USEOFFSETMAPPING\n"
2830 "uniform float OffsetMapping_Scale,\n"
2833 "#ifdef USEDEFERREDLIGHTMAP\n"
2834 "uniform half2 PixelToScreenTexCoord,\n"
2835 "uniform half3 DeferredMod_Diffuse,\n"
2836 "uniform half3 DeferredMod_Specular,\n"
2838 "uniform half3 Color_Ambient,\n"
2839 "uniform half3 Color_Diffuse,\n"
2840 "uniform half3 Color_Specular,\n"
2841 "uniform half SpecularPower,\n"
2843 "uniform half3 Color_Glow,\n"
2845 "uniform half Alpha,\n"
2846 "#ifdef USEREFLECTION\n"
2847 "uniform float4 DistortScaleRefractReflect,\n"
2848 "uniform float4 ScreenScaleRefractReflect,\n"
2849 "uniform float4 ScreenCenterRefractReflect,\n"
2850 "uniform half4 ReflectColor,\n"
2852 "#ifdef MODE_LIGHTDIRECTION\n"
2853 "uniform half3 LightColor,\n"
2855 "#ifdef MODE_LIGHTSOURCE\n"
2856 "uniform half3 LightColor,\n"
2859 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2860 "uniform sampler2D Texture_Attenuation,\n"
2861 "uniform samplerCUBE Texture_Cube,\n"
2863 "#ifdef USESHADOWMAPRECT\n"
2864 "# ifdef USESHADOWSAMPLER\n"
2865 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2867 "uniform samplerRECT Texture_ShadowMapRect,\n"
2871 "#ifdef USESHADOWMAP2D\n"
2872 "# ifdef USESHADOWSAMPLER\n"
2873 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2875 "uniform sampler2D Texture_ShadowMap2D,\n"
2879 "#ifdef USESHADOWMAPVSDCT\n"
2880 "uniform samplerCUBE Texture_CubeProjection,\n"
2883 "#ifdef USESHADOWMAPCUBE\n"
2884 "# ifdef USESHADOWSAMPLER\n"
2885 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2887 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2891 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2892 "uniform float2 ShadowMap_TextureScale,\n"
2893 "uniform float4 ShadowMap_Parameters,\n"
2895 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2897 "out float4 gl_FragColor : COLOR\n"
2900 " float2 TexCoord = TexCoordBoth.xy;\n"
2901 "#ifdef USEVERTEXTEXTUREBLEND\n"
2902 " float2 TexCoord2 = TexCoordBoth.zw;\n"
2904 "#ifdef USEOFFSETMAPPING\n"
2905 " // apply offsetmapping\n"
2906 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2907 "#define TexCoord TexCoordOffset\n"
2910 " // combine the diffuse textures (base, pants, shirt)\n"
2911 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2912 "#ifdef USEALPHAKILL\n"
2913 " if (color.a < 0.5)\n"
2916 " color.a *= Alpha;\n"
2917 "#ifdef USECOLORMAPPING\n"
2918 " color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2920 "#ifdef USEVERTEXTEXTUREBLEND\n"
2921 " float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2922 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2923 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2924 " color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2926 " //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2929 " // get the surface normal\n"
2930 "#ifdef USEVERTEXTEXTUREBLEND\n"
2931 " half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2933 " half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2936 " // get the material colors\n"
2937 " half3 diffusetex = color.rgb;\n"
2938 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2939 "# ifdef USEVERTEXTEXTUREBLEND\n"
2940 " half3 glosstex = half3(lerp(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2942 " half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2949 "#ifdef MODE_LIGHTSOURCE\n"
2950 " // light source\n"
2951 "#ifdef USEDIFFUSE\n"
2952 " half3 lightnormal = half3(normalize(LightVector));\n"
2953 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2954 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2955 "#ifdef USESPECULAR\n"
2956 "#ifdef USEEXACTSPECULARMATH\n"
2957 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2959 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2960 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2962 " color.rgb += glosstex * (specular * Color_Specular);\n"
2965 " color.rgb = diffusetex * Color_Ambient;\n"
2967 " color.rgb *= LightColor;\n"
2968 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2969 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2970 " color.rgb *= ShadowMapCompare(CubeVector,\n"
2971 "# if defined(USESHADOWMAP2D)\n"
2972 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2974 "# if defined(USESHADOWMAPRECT)\n"
2975 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2977 "# if defined(USESHADOWMAPCUBE)\n"
2978 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2981 "#ifdef USESHADOWMAPVSDCT\n"
2982 ", Texture_CubeProjection\n"
2987 "# ifdef USECUBEFILTER\n"
2988 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2990 "#endif // MODE_LIGHTSOURCE\n"
2995 "#ifdef MODE_LIGHTDIRECTION\n"
2997 "#ifdef USEDIFFUSE\n"
2998 " half3 lightnormal = half3(normalize(LightVector));\n"
3000 "#define lightcolor LightColor\n"
3001 "#endif // MODE_LIGHTDIRECTION\n"
3002 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3004 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3005 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3006 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3007 " // convert modelspace light vector to tangentspace\n"
3008 " half3 lightnormal;\n"
3009 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3010 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3011 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3012 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3013 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3014 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3015 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3016 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3017 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3018 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3019 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3020 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3021 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3022 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3023 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3025 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3026 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3027 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3033 "#ifdef MODE_LIGHTMAP\n"
3034 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3035 "#endif // MODE_LIGHTMAP\n"
3036 "#ifdef MODE_VERTEXCOLOR\n"
3037 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3038 "#endif // MODE_VERTEXCOLOR\n"
3039 "#ifdef MODE_FLATCOLOR\n"
3040 " color.rgb = diffusetex * Color_Ambient;\n"
3041 "#endif // MODE_FLATCOLOR\n"
3047 "# ifdef USEDIFFUSE\n"
3048 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3049 "# ifdef USESPECULAR\n"
3050 "# ifdef USEEXACTSPECULARMATH\n"
3051 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3053 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3054 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3056 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3058 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3061 " color.rgb = diffusetex * Color_Ambient;\n"
3065 "#ifdef USEDEFERREDLIGHTMAP\n"
3066 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3067 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3068 " color.rgb += glosstex * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3072 "#ifdef USEVERTEXTEXTUREBLEND\n"
3073 " color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3075 " color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3080 "#ifdef MODE_LIGHTSOURCE\n"
3081 " color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3083 " color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3087 " // 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"
3088 "#ifdef USEREFLECTION\n"
3089 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3090 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3091 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3092 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3093 " // FIXME temporary hack to detect the case that the reflection\n"
3094 " // gets blackened at edges due to leaving the area that contains actual\n"
3096 " // Remove this 'ack once we have a better way to stop this thing from\n"
3098 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3099 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3100 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3101 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3102 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3103 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3106 " gl_FragColor = float4(color);\n"
3108 "#endif // FRAGMENT_SHADER\n"
3110 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3111 "#endif // !MODE_DEFERREDGEOMETRY\n"
3112 "#endif // !MODE_WATER\n"
3113 "#endif // !MODE_REFRACTION\n"
3114 "#endif // !MODE_BLOOMBLUR\n"
3115 "#endif // !MODE_GENERIC\n"
3116 "#endif // !MODE_POSTPROCESS\n"
3117 "#endif // !MODE_SHOWDEPTH\n"
3118 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3121 //=======================================================================================================================================================
3123 typedef struct shaderpermutationinfo_s
3125 const char *pretext;
3128 shaderpermutationinfo_t;
3130 typedef struct shadermodeinfo_s
3132 const char *vertexfilename;
3133 const char *geometryfilename;
3134 const char *fragmentfilename;
3135 const char *pretext;
3140 typedef enum shaderpermutation_e
3142 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3143 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3144 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3145 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3146 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3147 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3148 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3149 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3150 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3151 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3152 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3153 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3154 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3155 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3156 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3157 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3158 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3159 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3160 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3161 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3162 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3163 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3164 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3165 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3166 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3167 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3168 SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3169 SHADERPERMUTATION_COUNT = 26 ///< size of shaderpermutationinfo array
3171 shaderpermutation_t;
3173 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3174 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3176 {"#define USEDIFFUSE\n", " diffuse"},
3177 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3178 {"#define USEVIEWTINT\n", " viewtint"},
3179 {"#define USECOLORMAPPING\n", " colormapping"},
3180 {"#define USESATURATION\n", " saturation"},
3181 {"#define USEFOGINSIDE\n", " foginside"},
3182 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3183 {"#define USEGAMMARAMPS\n", " gammaramps"},
3184 {"#define USECUBEFILTER\n", " cubefilter"},
3185 {"#define USEGLOW\n", " glow"},
3186 {"#define USEBLOOM\n", " bloom"},
3187 {"#define USESPECULAR\n", " specular"},
3188 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3189 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3190 {"#define USEREFLECTION\n", " reflection"},
3191 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3192 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3193 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3194 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3195 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3196 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3197 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3198 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3199 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3200 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3201 {"#define USEALPHAKILL\n", " alphakill"},
3204 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3205 typedef enum shadermode_e
3207 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3208 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3209 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3210 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3211 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3212 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3213 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3214 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3215 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3216 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3217 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3218 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3219 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3220 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3221 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3226 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3227 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3229 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3230 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3231 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3232 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3233 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3234 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3235 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3236 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3237 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3238 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3239 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3240 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3241 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3242 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3243 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3247 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3249 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3250 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3251 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3252 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3253 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3254 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3255 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3256 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3257 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3258 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3259 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3260 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3261 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3262 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3263 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3267 struct r_glsl_permutation_s;
3268 typedef struct r_glsl_permutation_s
3270 /// hash lookup data
3271 struct r_glsl_permutation_s *hashnext;
3273 unsigned int permutation;
3275 /// indicates if we have tried compiling this permutation already
3277 /// 0 if compilation failed
3279 /// locations of detected uniforms in program object, or -1 if not found
3280 int loc_Texture_First;
3281 int loc_Texture_Second;
3282 int loc_Texture_GammaRamps;
3283 int loc_Texture_Normal;
3284 int loc_Texture_Color;
3285 int loc_Texture_Gloss;
3286 int loc_Texture_Glow;
3287 int loc_Texture_SecondaryNormal;
3288 int loc_Texture_SecondaryColor;
3289 int loc_Texture_SecondaryGloss;
3290 int loc_Texture_SecondaryGlow;
3291 int loc_Texture_Pants;
3292 int loc_Texture_Shirt;
3293 int loc_Texture_FogMask;
3294 int loc_Texture_Lightmap;
3295 int loc_Texture_Deluxemap;
3296 int loc_Texture_Attenuation;
3297 int loc_Texture_Cube;
3298 int loc_Texture_Refraction;
3299 int loc_Texture_Reflection;
3300 int loc_Texture_ShadowMapRect;
3301 int loc_Texture_ShadowMapCube;
3302 int loc_Texture_ShadowMap2D;
3303 int loc_Texture_CubeProjection;
3304 int loc_Texture_ScreenDepth;
3305 int loc_Texture_ScreenNormalMap;
3306 int loc_Texture_ScreenDiffuse;
3307 int loc_Texture_ScreenSpecular;
3309 int loc_BloomBlur_Parameters;
3311 int loc_Color_Ambient;
3312 int loc_Color_Diffuse;
3313 int loc_Color_Specular;
3315 int loc_Color_Pants;
3316 int loc_Color_Shirt;
3317 int loc_DeferredColor_Ambient;
3318 int loc_DeferredColor_Diffuse;
3319 int loc_DeferredColor_Specular;
3320 int loc_DeferredMod_Diffuse;
3321 int loc_DeferredMod_Specular;
3322 int loc_DistortScaleRefractReflect;
3323 int loc_EyePosition;
3325 int loc_FogHeightFade;
3327 int loc_FogPlaneViewDist;
3328 int loc_FogRangeRecip;
3331 int loc_LightPosition;
3332 int loc_OffsetMapping_Scale;
3334 int loc_ReflectColor;
3335 int loc_ReflectFactor;
3336 int loc_ReflectOffset;
3337 int loc_RefractColor;
3339 int loc_ScreenCenterRefractReflect;
3340 int loc_ScreenScaleRefractReflect;
3341 int loc_ScreenToDepth;
3342 int loc_ShadowMap_Parameters;
3343 int loc_ShadowMap_TextureScale;
3344 int loc_SpecularPower;
3349 int loc_ViewTintColor;
3350 int loc_ViewToLight;
3351 int loc_ModelToLight;
3353 int loc_BackgroundTexMatrix;
3354 int loc_ModelViewProjectionMatrix;
3355 int loc_ModelViewMatrix;
3356 int loc_PixelToScreenTexCoord;
3358 r_glsl_permutation_t;
3360 #define SHADERPERMUTATION_HASHSIZE 256
3362 /// information about each possible shader permutation
3363 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3364 /// currently selected permutation
3365 r_glsl_permutation_t *r_glsl_permutation;
3366 /// storage for permutations linked in the hash table
3367 memexpandablearray_t r_glsl_permutationarray;
3369 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3371 //unsigned int hashdepth = 0;
3372 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3373 r_glsl_permutation_t *p;
3374 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3376 if (p->mode == mode && p->permutation == permutation)
3378 //if (hashdepth > 10)
3379 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3384 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3386 p->permutation = permutation;
3387 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3388 r_glsl_permutationhash[mode][hashindex] = p;
3389 //if (hashdepth > 10)
3390 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3394 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3397 if (!filename || !filename[0])
3399 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3402 if (printfromdisknotice)
3403 Con_DPrintf("from disk %s... ", filename);
3404 return shaderstring;
3406 else if (!strcmp(filename, "glsl/default.glsl"))
3408 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3409 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3411 return shaderstring;
3414 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3417 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3418 int vertstrings_count = 0;
3419 int geomstrings_count = 0;
3420 int fragstrings_count = 0;
3421 char *vertexstring, *geometrystring, *fragmentstring;
3422 const char *vertstrings_list[32+3];
3423 const char *geomstrings_list[32+3];
3424 const char *fragstrings_list[32+3];
3425 char permutationname[256];
3432 permutationname[0] = 0;
3433 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3434 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3435 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3437 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3439 // the first pretext is which type of shader to compile as
3440 // (later these will all be bound together as a program object)
3441 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3442 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3443 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3445 // the second pretext is the mode (for example a light source)
3446 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3447 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3448 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3449 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3451 // now add all the permutation pretexts
3452 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3454 if (permutation & (1<<i))
3456 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3457 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3458 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3459 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3463 // keep line numbers correct
3464 vertstrings_list[vertstrings_count++] = "\n";
3465 geomstrings_list[geomstrings_count++] = "\n";
3466 fragstrings_list[fragstrings_count++] = "\n";
3470 // now append the shader text itself
3471 vertstrings_list[vertstrings_count++] = vertexstring;
3472 geomstrings_list[geomstrings_count++] = geometrystring;
3473 fragstrings_list[fragstrings_count++] = fragmentstring;
3475 // if any sources were NULL, clear the respective list
3477 vertstrings_count = 0;
3478 if (!geometrystring)
3479 geomstrings_count = 0;
3480 if (!fragmentstring)
3481 fragstrings_count = 0;
3483 // compile the shader program
3484 if (vertstrings_count + geomstrings_count + fragstrings_count)
3485 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3489 qglUseProgramObjectARB(p->program);CHECKGLERROR
3490 // look up all the uniform variable names we care about, so we don't
3491 // have to look them up every time we set them
3493 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3494 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3495 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3496 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3497 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3498 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3499 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3500 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3501 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3502 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3503 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3504 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3505 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3506 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3507 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3508 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3509 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3510 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3511 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3512 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3513 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3514 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3515 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3516 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3517 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3518 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3519 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3520 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3521 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3522 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3523 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3524 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3525 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3526 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3527 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3528 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3529 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3530 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3531 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3532 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3533 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3534 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3535 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3536 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3537 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3538 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3539 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3540 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3541 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3542 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3543 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3544 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3545 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3546 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3547 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3548 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3549 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3550 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3551 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3552 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3553 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3554 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3555 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3556 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3557 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3558 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3559 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3560 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3561 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3562 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3563 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3564 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3565 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3566 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3567 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3568 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3569 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3570 // initialize the samplers to refer to the texture units we use
3571 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3572 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3573 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3574 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3575 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3576 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3577 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3578 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3579 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3580 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3581 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3582 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3583 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3584 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3585 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3586 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3587 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3588 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3589 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3590 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3591 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
3592 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
3593 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3594 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3595 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3596 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3597 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3598 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3600 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3603 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3607 Mem_Free(vertexstring);
3609 Mem_Free(geometrystring);
3611 Mem_Free(fragmentstring);
3614 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3616 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3617 if (r_glsl_permutation != perm)
3619 r_glsl_permutation = perm;
3620 if (!r_glsl_permutation->program)
3622 if (!r_glsl_permutation->compiled)
3623 R_GLSL_CompilePermutation(perm, mode, permutation);
3624 if (!r_glsl_permutation->program)
3626 // remove features until we find a valid permutation
3628 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3630 // reduce i more quickly whenever it would not remove any bits
3631 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3632 if (!(permutation & j))
3635 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3636 if (!r_glsl_permutation->compiled)
3637 R_GLSL_CompilePermutation(perm, mode, permutation);
3638 if (r_glsl_permutation->program)
3641 if (i >= SHADERPERMUTATION_COUNT)
3643 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3644 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3645 qglUseProgramObjectARB(0);CHECKGLERROR
3646 return; // no bit left to clear, entire mode is broken
3651 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3653 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3654 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3658 #include <Cg/cgGL.h>
3659 struct r_cg_permutation_s;
3660 typedef struct r_cg_permutation_s
3662 /// hash lookup data
3663 struct r_cg_permutation_s *hashnext;
3665 unsigned int permutation;
3667 /// indicates if we have tried compiling this permutation already
3669 /// 0 if compilation failed
3672 /// locations of detected parameters in programs, or NULL if not found
3673 CGparameter vp_EyePosition;
3674 CGparameter vp_FogPlane;
3675 CGparameter vp_LightDir;
3676 CGparameter vp_LightPosition;
3677 CGparameter vp_ModelToLight;
3678 CGparameter vp_TexMatrix;
3679 CGparameter vp_BackgroundTexMatrix;
3680 CGparameter vp_ModelViewProjectionMatrix;
3681 CGparameter vp_ModelViewMatrix;
3683 CGparameter fp_Texture_First;
3684 CGparameter fp_Texture_Second;
3685 CGparameter fp_Texture_GammaRamps;
3686 CGparameter fp_Texture_Normal;
3687 CGparameter fp_Texture_Color;
3688 CGparameter fp_Texture_Gloss;
3689 CGparameter fp_Texture_Glow;
3690 CGparameter fp_Texture_SecondaryNormal;
3691 CGparameter fp_Texture_SecondaryColor;
3692 CGparameter fp_Texture_SecondaryGloss;
3693 CGparameter fp_Texture_SecondaryGlow;
3694 CGparameter fp_Texture_Pants;
3695 CGparameter fp_Texture_Shirt;
3696 CGparameter fp_Texture_FogMask;
3697 CGparameter fp_Texture_Lightmap;
3698 CGparameter fp_Texture_Deluxemap;
3699 CGparameter fp_Texture_Attenuation;
3700 CGparameter fp_Texture_Cube;
3701 CGparameter fp_Texture_Refraction;
3702 CGparameter fp_Texture_Reflection;
3703 CGparameter fp_Texture_ShadowMapRect;
3704 CGparameter fp_Texture_ShadowMapCube;
3705 CGparameter fp_Texture_ShadowMap2D;
3706 CGparameter fp_Texture_CubeProjection;
3707 CGparameter fp_Texture_ScreenDepth;
3708 CGparameter fp_Texture_ScreenNormalMap;
3709 CGparameter fp_Texture_ScreenDiffuse;
3710 CGparameter fp_Texture_ScreenSpecular;
3711 CGparameter fp_Alpha;
3712 CGparameter fp_BloomBlur_Parameters;
3713 CGparameter fp_ClientTime;
3714 CGparameter fp_Color_Ambient;
3715 CGparameter fp_Color_Diffuse;
3716 CGparameter fp_Color_Specular;
3717 CGparameter fp_Color_Glow;
3718 CGparameter fp_Color_Pants;
3719 CGparameter fp_Color_Shirt;
3720 CGparameter fp_DeferredColor_Ambient;
3721 CGparameter fp_DeferredColor_Diffuse;
3722 CGparameter fp_DeferredColor_Specular;
3723 CGparameter fp_DeferredMod_Diffuse;
3724 CGparameter fp_DeferredMod_Specular;
3725 CGparameter fp_DistortScaleRefractReflect;
3726 CGparameter fp_EyePosition;
3727 CGparameter fp_FogColor;
3728 CGparameter fp_FogHeightFade;
3729 CGparameter fp_FogPlane;
3730 CGparameter fp_FogPlaneViewDist;
3731 CGparameter fp_FogRangeRecip;
3732 CGparameter fp_LightColor;
3733 CGparameter fp_LightDir;
3734 CGparameter fp_LightPosition;
3735 CGparameter fp_OffsetMapping_Scale;
3736 CGparameter fp_PixelSize;
3737 CGparameter fp_ReflectColor;
3738 CGparameter fp_ReflectFactor;
3739 CGparameter fp_ReflectOffset;
3740 CGparameter fp_RefractColor;
3741 CGparameter fp_Saturation;
3742 CGparameter fp_ScreenCenterRefractReflect;
3743 CGparameter fp_ScreenScaleRefractReflect;
3744 CGparameter fp_ScreenToDepth;
3745 CGparameter fp_ShadowMap_Parameters;
3746 CGparameter fp_ShadowMap_TextureScale;
3747 CGparameter fp_SpecularPower;
3748 CGparameter fp_UserVec1;
3749 CGparameter fp_UserVec2;
3750 CGparameter fp_UserVec3;
3751 CGparameter fp_UserVec4;
3752 CGparameter fp_ViewTintColor;
3753 CGparameter fp_ViewToLight;
3754 CGparameter fp_PixelToScreenTexCoord;
3758 /// information about each possible shader permutation
3759 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3760 /// currently selected permutation
3761 r_cg_permutation_t *r_cg_permutation;
3762 /// storage for permutations linked in the hash table
3763 memexpandablearray_t r_cg_permutationarray;
3765 #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));}}
3767 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3769 //unsigned int hashdepth = 0;
3770 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3771 r_cg_permutation_t *p;
3772 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3774 if (p->mode == mode && p->permutation == permutation)
3776 //if (hashdepth > 10)
3777 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3782 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3784 p->permutation = permutation;
3785 p->hashnext = r_cg_permutationhash[mode][hashindex];
3786 r_cg_permutationhash[mode][hashindex] = p;
3787 //if (hashdepth > 10)
3788 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3792 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3795 if (!filename || !filename[0])
3797 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3800 if (printfromdisknotice)
3801 Con_DPrintf("from disk %s... ", filename);
3802 return shaderstring;
3804 else if (!strcmp(filename, "cg/default.cg"))
3806 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3807 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3809 return shaderstring;
3812 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3815 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3816 int vertstrings_count = 0, vertstring_length = 0;
3817 int geomstrings_count = 0, geomstring_length = 0;
3818 int fragstrings_count = 0, fragstring_length = 0;
3820 char *vertexstring, *geometrystring, *fragmentstring;
3821 char *vertstring, *geomstring, *fragstring;
3822 const char *vertstrings_list[32+3];
3823 const char *geomstrings_list[32+3];
3824 const char *fragstrings_list[32+3];
3825 char permutationname[256];
3826 CGprofile vertexProfile;
3827 CGprofile fragmentProfile;
3835 permutationname[0] = 0;
3836 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
3837 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3838 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3840 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3842 // the first pretext is which type of shader to compile as
3843 // (later these will all be bound together as a program object)
3844 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3845 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3846 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3848 // the second pretext is the mode (for example a light source)
3849 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3850 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3851 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3852 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3854 // now add all the permutation pretexts
3855 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3857 if (permutation & (1<<i))
3859 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3860 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3861 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3862 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3866 // keep line numbers correct
3867 vertstrings_list[vertstrings_count++] = "\n";
3868 geomstrings_list[geomstrings_count++] = "\n";
3869 fragstrings_list[fragstrings_count++] = "\n";
3873 // now append the shader text itself
3874 vertstrings_list[vertstrings_count++] = vertexstring;
3875 geomstrings_list[geomstrings_count++] = geometrystring;
3876 fragstrings_list[fragstrings_count++] = fragmentstring;
3878 // if any sources were NULL, clear the respective list
3880 vertstrings_count = 0;
3881 if (!geometrystring)
3882 geomstrings_count = 0;
3883 if (!fragmentstring)
3884 fragstrings_count = 0;
3886 vertstring_length = 0;
3887 for (i = 0;i < vertstrings_count;i++)
3888 vertstring_length += strlen(vertstrings_list[i]);
3889 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3890 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3891 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3893 geomstring_length = 0;
3894 for (i = 0;i < geomstrings_count;i++)
3895 geomstring_length += strlen(geomstrings_list[i]);
3896 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3897 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3898 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3900 fragstring_length = 0;
3901 for (i = 0;i < fragstrings_count;i++)
3902 fragstring_length += strlen(fragstrings_list[i]);
3903 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3904 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3905 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3909 //vertexProfile = CG_PROFILE_ARBVP1;
3910 //fragmentProfile = CG_PROFILE_ARBFP1;
3911 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3912 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3913 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3914 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3915 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3918 // compile the vertex program
3919 if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL)))
3923 cgCompileProgram(p->vprogram);CHECKCGERROR
3924 if (!cgIsProgramCompiled(p->vprogram))
3927 cgDestroyProgram(p->vprogram);CHECKCGERROR
3933 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3934 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3935 // look up all the uniform variable names we care about, so we don't
3936 // have to look them up every time we set them
3938 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
3939 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
3940 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
3941 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
3942 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
3943 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
3944 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3945 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3946 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3951 // compile the fragment program
3952 if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL)))
3955 cgCompileProgram(p->fprogram);CHECKCGERROR
3956 if (!cgIsProgramCompiled(p->fprogram))
3959 cgDestroyProgram(p->fprogram);CHECKCGERROR
3965 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3966 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3968 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
3969 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
3970 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3971 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3972 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
3973 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3974 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3975 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3976 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3977 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3978 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3979 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3980 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3981 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3982 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3983 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3984 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3985 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3986 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3987 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3988 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3989 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3990 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3991 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3992 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3993 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3994 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3995 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3996 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
3997 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3998 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
3999 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4000 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4001 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4002 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4003 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4004 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4005 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4006 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4007 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4008 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4009 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4010 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4011 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4012 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4013 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4014 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4015 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4016 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4017 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4018 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4019 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4020 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4021 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4022 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4023 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4024 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4025 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4026 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4027 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4028 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4029 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4030 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4031 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4032 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4033 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4034 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4035 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4036 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4037 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4038 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4039 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4044 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4045 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4047 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4051 Mem_Free(vertstring);
4053 Mem_Free(geomstring);
4055 Mem_Free(fragstring);
4057 Mem_Free(vertexstring);
4059 Mem_Free(geometrystring);
4061 Mem_Free(fragmentstring);
4064 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4066 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4069 if (r_cg_permutation != perm)
4071 r_cg_permutation = perm;
4072 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4074 if (!r_cg_permutation->compiled)
4075 R_CG_CompilePermutation(perm, mode, permutation);
4076 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4078 // remove features until we find a valid permutation
4080 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4082 // reduce i more quickly whenever it would not remove any bits
4083 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4084 if (!(permutation & j))
4087 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4088 if (!r_cg_permutation->compiled)
4089 R_CG_CompilePermutation(perm, mode, permutation);
4090 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4093 if (i >= SHADERPERMUTATION_COUNT)
4095 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4096 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4097 return; // no bit left to clear, entire mode is broken
4103 if (r_cg_permutation->vprogram)
4105 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4106 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4107 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4111 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4112 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4114 if (r_cg_permutation->fprogram)
4116 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4117 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4118 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4122 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4123 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4127 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4128 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4131 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4133 cgGLSetTextureParameter(param, R_GetTexture(tex));
4134 cgGLEnableTextureParameter(param);
4138 void R_GLSL_Restart_f(void)
4140 unsigned int i, limit;
4141 switch(vid.renderpath)
4143 case RENDERPATH_GL20:
4145 r_glsl_permutation_t *p;
4146 r_glsl_permutation = NULL;
4147 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4148 for (i = 0;i < limit;i++)
4150 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4152 GL_Backend_FreeProgram(p->program);
4153 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4156 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4159 case RENDERPATH_CGGL:
4162 r_cg_permutation_t *p;
4163 r_cg_permutation = NULL;
4164 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4165 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4166 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4167 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4168 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4169 for (i = 0;i < limit;i++)
4171 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4174 cgDestroyProgram(p->vprogram);
4176 cgDestroyProgram(p->fprogram);
4177 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4180 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4184 case RENDERPATH_GL13:
4185 case RENDERPATH_GL11:
4190 void R_GLSL_DumpShader_f(void)
4195 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4198 FS_Print(file, "/* The engine may define the following macros:\n");
4199 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4200 for (i = 0;i < SHADERMODE_COUNT;i++)
4201 FS_Print(file, glslshadermodeinfo[i].pretext);
4202 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4203 FS_Print(file, shaderpermutationinfo[i].pretext);
4204 FS_Print(file, "*/\n");
4205 FS_Print(file, builtinshaderstring);
4207 Con_Printf("glsl/default.glsl written\n");
4210 Con_Printf("failed to write to glsl/default.glsl\n");
4213 file = FS_OpenRealFile("cg/default.cg", "w", false);
4216 FS_Print(file, "/* The engine may define the following macros:\n");
4217 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4218 for (i = 0;i < SHADERMODE_COUNT;i++)
4219 FS_Print(file, cgshadermodeinfo[i].pretext);
4220 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4221 FS_Print(file, shaderpermutationinfo[i].pretext);
4222 FS_Print(file, "*/\n");
4223 FS_Print(file, builtincgshaderstring);
4225 Con_Printf("cg/default.cg written\n");
4228 Con_Printf("failed to write to cg/default.cg\n");
4232 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4235 texturemode = GL_MODULATE;
4236 switch (vid.renderpath)
4238 case RENDERPATH_GL20:
4239 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))));
4240 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4241 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4243 case RENDERPATH_CGGL:
4246 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))));
4247 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4248 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4251 case RENDERPATH_GL13:
4252 R_Mesh_TexBind(0, first );
4253 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4254 R_Mesh_TexBind(1, second);
4256 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4258 case RENDERPATH_GL11:
4259 R_Mesh_TexBind(0, first );
4264 void R_SetupShader_DepthOrShadow(void)
4266 switch (vid.renderpath)
4268 case RENDERPATH_GL20:
4269 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4271 case RENDERPATH_CGGL:
4273 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4276 case RENDERPATH_GL13:
4277 R_Mesh_TexBind(0, 0);
4278 R_Mesh_TexBind(1, 0);
4280 case RENDERPATH_GL11:
4281 R_Mesh_TexBind(0, 0);
4286 void R_SetupShader_ShowDepth(void)
4288 switch (vid.renderpath)
4290 case RENDERPATH_GL20:
4291 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4293 case RENDERPATH_CGGL:
4295 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4298 case RENDERPATH_GL13:
4300 case RENDERPATH_GL11:
4305 extern qboolean r_shadow_usingdeferredprepass;
4306 extern cvar_t r_shadow_deferred_8bitrange;
4307 extern rtexture_t *r_shadow_attenuationgradienttexture;
4308 extern rtexture_t *r_shadow_attenuation2dtexture;
4309 extern rtexture_t *r_shadow_attenuation3dtexture;
4310 extern qboolean r_shadow_usingshadowmaprect;
4311 extern qboolean r_shadow_usingshadowmapcube;
4312 extern qboolean r_shadow_usingshadowmap2d;
4313 extern float r_shadow_shadowmap_texturescale[2];
4314 extern float r_shadow_shadowmap_parameters[4];
4315 extern qboolean r_shadow_shadowmapvsdct;
4316 extern qboolean r_shadow_shadowmapsampler;
4317 extern int r_shadow_shadowmappcf;
4318 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4319 extern rtexture_t *r_shadow_shadowmap2dtexture;
4320 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4321 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4322 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4323 extern int r_shadow_prepass_width;
4324 extern int r_shadow_prepass_height;
4325 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4326 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4327 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4328 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4329 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4331 // select a permutation of the lighting shader appropriate to this
4332 // combination of texture, entity, light source, and fogging, only use the
4333 // minimum features necessary to avoid wasting rendering time in the
4334 // fragment shader on features that are not being used
4335 unsigned int permutation = 0;
4336 unsigned int mode = 0;
4338 if (rsurfacepass == RSURFPASS_BACKGROUND)
4340 // distorted background
4341 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4342 mode = SHADERMODE_WATER;
4344 mode = SHADERMODE_REFRACTION;
4345 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4346 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4347 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4348 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4349 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4350 R_Mesh_ColorPointer(NULL, 0, 0);
4351 GL_AlphaTest(false);
4352 GL_BlendFunc(GL_ONE, GL_ZERO);
4354 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4356 if (r_glsl_offsetmapping.integer)
4358 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4359 if (r_glsl_offsetmapping_reliefmapping.integer)
4360 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4362 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4363 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4364 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4365 permutation |= SHADERPERMUTATION_ALPHAKILL;
4366 // normalmap (deferred prepass), may use alpha test on diffuse
4367 mode = SHADERMODE_DEFERREDGEOMETRY;
4368 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4369 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4370 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4371 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4372 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4373 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4374 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4375 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4376 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4378 R_Mesh_ColorPointer(NULL, 0, 0);
4379 GL_AlphaTest(false);
4380 GL_BlendFunc(GL_ONE, GL_ZERO);
4382 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4384 if (r_glsl_offsetmapping.integer)
4386 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4387 if (r_glsl_offsetmapping_reliefmapping.integer)
4388 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4390 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4391 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4393 mode = SHADERMODE_LIGHTSOURCE;
4394 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4395 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4396 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4397 permutation |= SHADERPERMUTATION_CUBEFILTER;
4398 if (diffusescale > 0)
4399 permutation |= SHADERPERMUTATION_DIFFUSE;
4400 if (specularscale > 0)
4402 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4403 if (r_shadow_glossexact.integer)
4404 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4406 if (r_refdef.fogenabled)
4407 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4408 if (rsurface.texture->colormapping)
4409 permutation |= SHADERPERMUTATION_COLORMAPPING;
4410 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4412 if (r_shadow_usingshadowmaprect)
4413 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4414 if (r_shadow_usingshadowmap2d)
4415 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4416 if (r_shadow_usingshadowmapcube)
4417 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4418 else if(r_shadow_shadowmapvsdct)
4419 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4421 if (r_shadow_shadowmapsampler)
4422 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4423 if (r_shadow_shadowmappcf > 1)
4424 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4425 else if (r_shadow_shadowmappcf)
4426 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4428 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4429 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4431 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4432 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4433 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4437 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4438 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4439 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4441 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4442 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4443 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4445 R_Mesh_ColorPointer(NULL, 0, 0);
4446 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4447 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4449 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4451 if (r_glsl_offsetmapping.integer)
4453 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4454 if (r_glsl_offsetmapping_reliefmapping.integer)
4455 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4457 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4458 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4459 // unshaded geometry (fullbright or ambient model lighting)
4460 mode = SHADERMODE_FLATCOLOR;
4461 ambientscale = diffusescale = specularscale = 0;
4462 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4463 permutation |= SHADERPERMUTATION_GLOW;
4464 if (r_refdef.fogenabled)
4465 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4466 if (rsurface.texture->colormapping)
4467 permutation |= SHADERPERMUTATION_COLORMAPPING;
4468 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4469 permutation |= SHADERPERMUTATION_REFLECTION;
4470 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4471 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4473 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4474 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4475 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4479 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4480 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4481 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4483 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4484 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4485 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4487 R_Mesh_ColorPointer(NULL, 0, 0);
4488 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4489 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4491 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4493 if (r_glsl_offsetmapping.integer)
4495 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4496 if (r_glsl_offsetmapping_reliefmapping.integer)
4497 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4499 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4500 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4501 // directional model lighting
4502 mode = SHADERMODE_LIGHTDIRECTION;
4503 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4504 permutation |= SHADERPERMUTATION_GLOW;
4505 permutation |= SHADERPERMUTATION_DIFFUSE;
4506 if (specularscale > 0)
4508 permutation |= SHADERPERMUTATION_SPECULAR;
4509 if (r_shadow_glossexact.integer)
4510 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4512 if (r_refdef.fogenabled)
4513 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4514 if (rsurface.texture->colormapping)
4515 permutation |= SHADERPERMUTATION_COLORMAPPING;
4516 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4517 permutation |= SHADERPERMUTATION_REFLECTION;
4518 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4519 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4520 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4521 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4523 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4524 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4525 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4529 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4530 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4531 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4533 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4534 R_Mesh_ColorPointer(NULL, 0, 0);
4535 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4536 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4538 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4540 if (r_glsl_offsetmapping.integer)
4542 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4543 if (r_glsl_offsetmapping_reliefmapping.integer)
4544 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4546 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4547 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4548 // ambient model lighting
4549 mode = SHADERMODE_LIGHTDIRECTION;
4550 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4551 permutation |= SHADERPERMUTATION_GLOW;
4552 if (r_refdef.fogenabled)
4553 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4554 if (rsurface.texture->colormapping)
4555 permutation |= SHADERPERMUTATION_COLORMAPPING;
4556 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4557 permutation |= SHADERPERMUTATION_REFLECTION;
4558 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4559 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4560 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4561 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4563 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4564 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4565 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4569 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4570 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4571 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4573 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4574 R_Mesh_ColorPointer(NULL, 0, 0);
4575 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4576 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4580 if (r_glsl_offsetmapping.integer)
4582 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4583 if (r_glsl_offsetmapping_reliefmapping.integer)
4584 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4586 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4587 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4589 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4590 permutation |= SHADERPERMUTATION_GLOW;
4591 if (r_refdef.fogenabled)
4592 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4593 if (rsurface.texture->colormapping)
4594 permutation |= SHADERPERMUTATION_COLORMAPPING;
4595 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4596 permutation |= SHADERPERMUTATION_REFLECTION;
4597 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4598 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4599 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4601 // deluxemapping (light direction texture)
4602 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4603 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4605 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4606 permutation |= SHADERPERMUTATION_DIFFUSE;
4607 if (specularscale > 0)
4609 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4610 if (r_shadow_glossexact.integer)
4611 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4613 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4614 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4615 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4617 R_Mesh_ColorPointer(NULL, 0, 0);
4619 else if (r_glsl_deluxemapping.integer >= 2)
4621 // fake deluxemapping (uniform light direction in tangentspace)
4622 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4623 permutation |= SHADERPERMUTATION_DIFFUSE;
4624 if (specularscale > 0)
4626 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4627 if (r_shadow_glossexact.integer)
4628 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4630 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4631 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4632 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4634 R_Mesh_ColorPointer(NULL, 0, 0);
4636 else if (rsurface.uselightmaptexture)
4638 // ordinary lightmapping (q1bsp, q3bsp)
4639 mode = SHADERMODE_LIGHTMAP;
4640 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4641 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4642 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4644 R_Mesh_ColorPointer(NULL, 0, 0);
4648 // ordinary vertex coloring (q3bsp)
4649 mode = SHADERMODE_VERTEXCOLOR;
4650 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4651 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4653 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4654 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4656 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4657 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4658 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4662 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4663 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4664 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4666 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4667 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4669 switch(vid.renderpath)
4671 case RENDERPATH_GL20:
4672 R_SetupShader_SetPermutationGLSL(mode, permutation);
4673 if (mode == SHADERMODE_LIGHTSOURCE)
4675 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4676 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4677 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4678 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);
4679 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);
4680 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);
4682 // additive passes are only darkened by fog, not tinted
4683 if (r_glsl_permutation->loc_FogColor >= 0)
4684 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4685 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]);
4686 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]);
4687 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4691 if (mode == SHADERMODE_FLATCOLOR)
4693 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4695 else if (mode == SHADERMODE_LIGHTDIRECTION)
4697 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]);
4698 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]);
4699 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);
4700 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);
4701 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);
4702 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]);
4703 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]);
4707 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]);
4708 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]);
4709 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);
4710 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);
4711 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);
4713 // additive passes are only darkened by fog, not tinted
4714 if (r_glsl_permutation->loc_FogColor >= 0)
4716 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4717 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4719 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4721 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);
4722 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]);
4723 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]);
4724 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4725 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4726 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4727 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4728 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4730 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4731 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4732 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4733 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4734 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4735 if (r_glsl_permutation->loc_Color_Pants >= 0)
4737 if (rsurface.texture->pantstexture)
4738 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4740 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4742 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4744 if (rsurface.texture->shirttexture)
4745 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4747 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4749 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]);
4750 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4751 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4752 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4753 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4754 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]);
4755 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4757 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
4758 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
4759 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
4760 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
4761 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
4762 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
4763 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
4764 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
4765 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
4766 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
4767 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
4768 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
4769 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
4770 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
4771 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white );
4772 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_blanknormalmap );
4773 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
4774 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , r_texture_white );
4775 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , r_texture_white );
4776 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
4777 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
4778 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
4779 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
4780 if (rsurface.rtlight)
4782 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
4783 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
4784 if (r_shadow_usingshadowmapcube)
4785 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4786 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
4787 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
4791 case RENDERPATH_CGGL:
4793 R_SetupShader_SetPermutationCG(mode, permutation);
4794 if (mode == SHADERMODE_LIGHTSOURCE)
4796 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4797 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4801 if (mode == SHADERMODE_LIGHTDIRECTION)
4803 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
4806 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4807 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4808 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4809 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
4812 if (mode == SHADERMODE_LIGHTSOURCE)
4814 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4815 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4816 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
4817 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
4818 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
4820 // additive passes are only darkened by fog, not tinted
4821 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4822 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
4823 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
4824 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4828 if (mode == SHADERMODE_FLATCOLOR)
4830 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4832 else if (mode == SHADERMODE_LIGHTDIRECTION)
4834 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
4835 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
4836 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
4837 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
4838 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
4839 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
4840 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
4844 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
4845 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
4846 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
4847 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
4848 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
4850 // additive passes are only darkened by fog, not tinted
4851 if (r_cg_permutation->fp_FogColor)
4853 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4854 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4856 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4859 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
4860 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
4861 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
4862 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4863 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4864 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4865 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4866 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4868 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4869 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4870 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4871 if (r_cg_permutation->fp_Color_Pants)
4873 if (rsurface.texture->pantstexture)
4874 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4876 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4879 if (r_cg_permutation->fp_Color_Shirt)
4881 if (rsurface.texture->shirttexture)
4882 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4884 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4887 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
4888 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4889 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4890 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4891 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4892 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
4893 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
4895 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
4896 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
4897 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
4898 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
4899 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
4900 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
4901 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
4902 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
4903 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
4904 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
4905 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
4906 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
4907 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
4908 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
4909 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , r_texture_white );CHECKCGERROR
4910 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , r_texture_blanknormalmap );CHECKCGERROR
4911 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
4912 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , r_texture_white );CHECKCGERROR
4913 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , r_texture_white );CHECKCGERROR
4914 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
4915 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
4916 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
4917 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
4918 if (rsurface.rtlight)
4920 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
4921 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
4922 if (r_shadow_usingshadowmapcube)
4923 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4924 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
4925 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
4931 case RENDERPATH_GL13:
4932 case RENDERPATH_GL11:
4937 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4939 // select a permutation of the lighting shader appropriate to this
4940 // combination of texture, entity, light source, and fogging, only use the
4941 // minimum features necessary to avoid wasting rendering time in the
4942 // fragment shader on features that are not being used
4943 unsigned int permutation = 0;
4944 unsigned int mode = 0;
4945 const float *lightcolorbase = rtlight->currentcolor;
4946 float ambientscale = rtlight->ambientscale;
4947 float diffusescale = rtlight->diffusescale;
4948 float specularscale = rtlight->specularscale;
4949 // this is the location of the light in view space
4950 vec3_t viewlightorigin;
4951 // this transforms from view space (camera) to light space (cubemap)
4952 matrix4x4_t viewtolight;
4953 matrix4x4_t lighttoview;
4954 float viewtolight16f[16];
4955 float range = 1.0f / r_shadow_deferred_8bitrange.value;
4957 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4958 if (rtlight->currentcubemap != r_texture_whitecube)
4959 permutation |= SHADERPERMUTATION_CUBEFILTER;
4960 if (diffusescale > 0)
4961 permutation |= SHADERPERMUTATION_DIFFUSE;
4962 if (specularscale > 0)
4964 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4965 if (r_shadow_glossexact.integer)
4966 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4968 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4970 if (r_shadow_usingshadowmaprect)
4971 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4972 if (r_shadow_usingshadowmap2d)
4973 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4974 if (r_shadow_usingshadowmapcube)
4975 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4976 else if(r_shadow_shadowmapvsdct)
4977 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4979 if (r_shadow_shadowmapsampler)
4980 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4981 if (r_shadow_shadowmappcf > 1)
4982 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4983 else if (r_shadow_shadowmappcf)
4984 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4986 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4987 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4988 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4989 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4990 switch(vid.renderpath)
4992 case RENDERPATH_GL20:
4993 R_SetupShader_SetPermutationGLSL(mode, permutation);
4994 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4995 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
4996 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);
4997 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);
4998 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);
4999 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]);
5000 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]);
5001 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));
5002 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]);
5003 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5005 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5006 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5007 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5008 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5009 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
5010 if (r_shadow_usingshadowmapcube)
5011 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5012 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5013 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5015 case RENDERPATH_CGGL:
5017 R_SetupShader_SetPermutationCG(mode, permutation);
5018 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5019 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5020 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
5021 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
5022 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
5023 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
5024 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
5025 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
5026 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
5027 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5029 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5030 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5031 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5032 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5033 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5034 if (r_shadow_usingshadowmapcube)
5035 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5036 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5037 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5040 case RENDERPATH_GL13:
5041 case RENDERPATH_GL11:
5046 #define SKINFRAME_HASH 1024
5050 int loadsequence; // incremented each level change
5051 memexpandablearray_t array;
5052 skinframe_t *hash[SKINFRAME_HASH];
5055 r_skinframe_t r_skinframe;
5057 void R_SkinFrame_PrepareForPurge(void)
5059 r_skinframe.loadsequence++;
5060 // wrap it without hitting zero
5061 if (r_skinframe.loadsequence >= 200)
5062 r_skinframe.loadsequence = 1;
5065 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5069 // mark the skinframe as used for the purging code
5070 skinframe->loadsequence = r_skinframe.loadsequence;
5073 void R_SkinFrame_Purge(void)
5077 for (i = 0;i < SKINFRAME_HASH;i++)
5079 for (s = r_skinframe.hash[i];s;s = s->next)
5081 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5083 if (s->merged == s->base)
5085 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5086 R_PurgeTexture(s->stain );s->stain = NULL;
5087 R_PurgeTexture(s->merged);s->merged = NULL;
5088 R_PurgeTexture(s->base );s->base = NULL;
5089 R_PurgeTexture(s->pants );s->pants = NULL;
5090 R_PurgeTexture(s->shirt );s->shirt = NULL;
5091 R_PurgeTexture(s->nmap );s->nmap = NULL;
5092 R_PurgeTexture(s->gloss );s->gloss = NULL;
5093 R_PurgeTexture(s->glow );s->glow = NULL;
5094 R_PurgeTexture(s->fog );s->fog = NULL;
5095 s->loadsequence = 0;
5101 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5103 char basename[MAX_QPATH];
5105 Image_StripImageExtension(name, basename, sizeof(basename));
5107 if( last == NULL ) {
5109 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5110 item = r_skinframe.hash[hashindex];
5115 // linearly search through the hash bucket
5116 for( ; item ; item = item->next ) {
5117 if( !strcmp( item->basename, basename ) ) {
5124 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5128 char basename[MAX_QPATH];
5130 Image_StripImageExtension(name, basename, sizeof(basename));
5132 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5133 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5134 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5138 rtexture_t *dyntexture;
5139 // check whether its a dynamic texture
5140 dyntexture = CL_GetDynTexture( basename );
5141 if (!add && !dyntexture)
5143 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5144 memset(item, 0, sizeof(*item));
5145 strlcpy(item->basename, basename, sizeof(item->basename));
5146 item->base = dyntexture; // either NULL or dyntexture handle
5147 item->textureflags = textureflags;
5148 item->comparewidth = comparewidth;
5149 item->compareheight = compareheight;
5150 item->comparecrc = comparecrc;
5151 item->next = r_skinframe.hash[hashindex];
5152 r_skinframe.hash[hashindex] = item;
5154 else if( item->base == NULL )
5156 rtexture_t *dyntexture;
5157 // check whether its a dynamic texture
5158 // 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]
5159 dyntexture = CL_GetDynTexture( basename );
5160 item->base = dyntexture; // either NULL or dyntexture handle
5163 R_SkinFrame_MarkUsed(item);
5167 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5169 unsigned long long avgcolor[5], wsum; \
5177 for(pix = 0; pix < cnt; ++pix) \
5180 for(comp = 0; comp < 3; ++comp) \
5182 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5185 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5187 for(comp = 0; comp < 3; ++comp) \
5188 avgcolor[comp] += getpixel * w; \
5191 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5192 avgcolor[4] += getpixel; \
5194 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5196 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5197 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5198 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5199 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5202 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5205 unsigned char *pixels;
5206 unsigned char *bumppixels;
5207 unsigned char *basepixels = NULL;
5208 int basepixels_width = 0;
5209 int basepixels_height = 0;
5210 skinframe_t *skinframe;
5211 rtexture_t *ddsbase = NULL;
5212 qboolean ddshasalpha = false;
5213 float ddsavgcolor[4];
5214 char basename[MAX_QPATH];
5216 if (cls.state == ca_dedicated)
5219 // return an existing skinframe if already loaded
5220 // if loading of the first image fails, don't make a new skinframe as it
5221 // would cause all future lookups of this to be missing
5222 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5223 if (skinframe && skinframe->base)
5226 Image_StripImageExtension(name, basename, sizeof(basename));
5228 // check for DDS texture file first
5229 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5231 basepixels = loadimagepixelsbgra(name, complain, true);
5232 if (basepixels == NULL)
5236 if (developer_loading.integer)
5237 Con_Printf("loading skin \"%s\"\n", name);
5239 // we've got some pixels to store, so really allocate this new texture now
5241 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5242 skinframe->stain = NULL;
5243 skinframe->merged = NULL;
5244 skinframe->base = NULL;
5245 skinframe->pants = NULL;
5246 skinframe->shirt = NULL;
5247 skinframe->nmap = NULL;
5248 skinframe->gloss = NULL;
5249 skinframe->glow = NULL;
5250 skinframe->fog = NULL;
5251 skinframe->hasalpha = false;
5255 skinframe->base = ddsbase;
5256 skinframe->hasalpha = ddshasalpha;
5257 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5258 if (r_loadfog && skinframe->hasalpha)
5259 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5260 //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]);
5264 basepixels_width = image_width;
5265 basepixels_height = image_height;
5266 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);
5267 if (textureflags & TEXF_ALPHA)
5269 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5271 if (basepixels[j] < 255)
5273 skinframe->hasalpha = true;
5277 if (r_loadfog && skinframe->hasalpha)
5279 // has transparent pixels
5280 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5281 for (j = 0;j < image_width * image_height * 4;j += 4)
5286 pixels[j+3] = basepixels[j+3];
5288 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);
5292 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5293 //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]);
5294 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5295 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5296 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5297 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5302 if (r_loadnormalmap)
5303 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5304 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5306 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5307 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5308 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5311 // _norm is the name used by tenebrae and has been adopted as standard
5312 if (r_loadnormalmap && skinframe->nmap == NULL)
5314 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5316 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);
5320 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5322 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5323 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5324 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);
5326 Mem_Free(bumppixels);
5328 else if (r_shadow_bumpscale_basetexture.value > 0)
5330 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5331 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5332 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);
5335 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5336 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5339 // _luma is supported only for tenebrae compatibility
5340 // _glow is the preferred name
5341 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5343 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);
5344 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5345 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5346 Mem_Free(pixels);pixels = NULL;
5349 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5351 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);
5352 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5353 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5358 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5360 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);
5361 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5362 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5367 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5369 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);
5370 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5371 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5377 Mem_Free(basepixels);
5382 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5383 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5386 unsigned char *temp1, *temp2;
5387 skinframe_t *skinframe;
5389 if (cls.state == ca_dedicated)
5392 // if already loaded just return it, otherwise make a new skinframe
5393 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5394 if (skinframe && skinframe->base)
5397 skinframe->stain = NULL;
5398 skinframe->merged = NULL;
5399 skinframe->base = NULL;
5400 skinframe->pants = NULL;
5401 skinframe->shirt = NULL;
5402 skinframe->nmap = NULL;
5403 skinframe->gloss = NULL;
5404 skinframe->glow = NULL;
5405 skinframe->fog = NULL;
5406 skinframe->hasalpha = false;
5408 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5412 if (developer_loading.integer)
5413 Con_Printf("loading 32bit skin \"%s\"\n", name);
5415 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5417 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5418 temp2 = temp1 + width * height * 4;
5419 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5420 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5423 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5424 if (textureflags & TEXF_ALPHA)
5426 for (i = 3;i < width * height * 4;i += 4)
5428 if (skindata[i] < 255)
5430 skinframe->hasalpha = true;
5434 if (r_loadfog && skinframe->hasalpha)
5436 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5437 memcpy(fogpixels, skindata, width * height * 4);
5438 for (i = 0;i < width * height * 4;i += 4)
5439 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5440 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5441 Mem_Free(fogpixels);
5445 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5446 //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]);
5451 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5455 skinframe_t *skinframe;
5457 if (cls.state == ca_dedicated)
5460 // if already loaded just return it, otherwise make a new skinframe
5461 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5462 if (skinframe && skinframe->base)
5465 skinframe->stain = NULL;
5466 skinframe->merged = NULL;
5467 skinframe->base = NULL;
5468 skinframe->pants = NULL;
5469 skinframe->shirt = NULL;
5470 skinframe->nmap = NULL;
5471 skinframe->gloss = NULL;
5472 skinframe->glow = NULL;
5473 skinframe->fog = NULL;
5474 skinframe->hasalpha = false;
5476 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5480 if (developer_loading.integer)
5481 Con_Printf("loading quake skin \"%s\"\n", name);
5483 // 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)
5484 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5485 memcpy(skinframe->qpixels, skindata, width*height);
5486 skinframe->qwidth = width;
5487 skinframe->qheight = height;
5490 for (i = 0;i < width * height;i++)
5491 featuresmask |= palette_featureflags[skindata[i]];
5493 skinframe->hasalpha = false;
5494 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5495 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5496 skinframe->qgeneratemerged = true;
5497 skinframe->qgeneratebase = skinframe->qhascolormapping;
5498 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5500 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5501 //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]);
5506 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5510 unsigned char *skindata;
5512 if (!skinframe->qpixels)
5515 if (!skinframe->qhascolormapping)
5516 colormapped = false;
5520 if (!skinframe->qgeneratebase)
5525 if (!skinframe->qgeneratemerged)
5529 width = skinframe->qwidth;
5530 height = skinframe->qheight;
5531 skindata = skinframe->qpixels;
5533 if (skinframe->qgeneratenmap)
5535 unsigned char *temp1, *temp2;
5536 skinframe->qgeneratenmap = false;
5537 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5538 temp2 = temp1 + width * height * 4;
5539 // use either a custom palette or the quake palette
5540 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5541 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5542 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5546 if (skinframe->qgenerateglow)
5548 skinframe->qgenerateglow = false;
5549 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5554 skinframe->qgeneratebase = false;
5555 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);
5556 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5557 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5561 skinframe->qgeneratemerged = false;
5562 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5565 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5567 Mem_Free(skinframe->qpixels);
5568 skinframe->qpixels = NULL;
5572 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)
5575 skinframe_t *skinframe;
5577 if (cls.state == ca_dedicated)
5580 // if already loaded just return it, otherwise make a new skinframe
5581 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5582 if (skinframe && skinframe->base)
5585 skinframe->stain = NULL;
5586 skinframe->merged = NULL;
5587 skinframe->base = NULL;
5588 skinframe->pants = NULL;
5589 skinframe->shirt = NULL;
5590 skinframe->nmap = NULL;
5591 skinframe->gloss = NULL;
5592 skinframe->glow = NULL;
5593 skinframe->fog = NULL;
5594 skinframe->hasalpha = false;
5596 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5600 if (developer_loading.integer)
5601 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5603 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5604 if (textureflags & TEXF_ALPHA)
5606 for (i = 0;i < width * height;i++)
5608 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5610 skinframe->hasalpha = true;
5614 if (r_loadfog && skinframe->hasalpha)
5615 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5618 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5619 //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]);
5624 skinframe_t *R_SkinFrame_LoadMissing(void)
5626 skinframe_t *skinframe;
5628 if (cls.state == ca_dedicated)
5631 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5632 skinframe->stain = NULL;
5633 skinframe->merged = NULL;
5634 skinframe->base = NULL;
5635 skinframe->pants = NULL;
5636 skinframe->shirt = NULL;
5637 skinframe->nmap = NULL;
5638 skinframe->gloss = NULL;
5639 skinframe->glow = NULL;
5640 skinframe->fog = NULL;
5641 skinframe->hasalpha = false;
5643 skinframe->avgcolor[0] = rand() / RAND_MAX;
5644 skinframe->avgcolor[1] = rand() / RAND_MAX;
5645 skinframe->avgcolor[2] = rand() / RAND_MAX;
5646 skinframe->avgcolor[3] = 1;
5651 void R_Main_FreeViewCache(void)
5653 if (r_refdef.viewcache.entityvisible)
5654 Mem_Free(r_refdef.viewcache.entityvisible);
5655 if (r_refdef.viewcache.world_pvsbits)
5656 Mem_Free(r_refdef.viewcache.world_pvsbits);
5657 if (r_refdef.viewcache.world_leafvisible)
5658 Mem_Free(r_refdef.viewcache.world_leafvisible);
5659 if (r_refdef.viewcache.world_surfacevisible)
5660 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5661 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5664 void R_Main_ResizeViewCache(void)
5666 int numentities = r_refdef.scene.numentities;
5667 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5668 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5669 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5670 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5671 if (r_refdef.viewcache.maxentities < numentities)
5673 r_refdef.viewcache.maxentities = numentities;
5674 if (r_refdef.viewcache.entityvisible)
5675 Mem_Free(r_refdef.viewcache.entityvisible);
5676 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5678 if (r_refdef.viewcache.world_numclusters != numclusters)
5680 r_refdef.viewcache.world_numclusters = numclusters;
5681 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5682 if (r_refdef.viewcache.world_pvsbits)
5683 Mem_Free(r_refdef.viewcache.world_pvsbits);
5684 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5686 if (r_refdef.viewcache.world_numleafs != numleafs)
5688 r_refdef.viewcache.world_numleafs = numleafs;
5689 if (r_refdef.viewcache.world_leafvisible)
5690 Mem_Free(r_refdef.viewcache.world_leafvisible);
5691 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5693 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5695 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5696 if (r_refdef.viewcache.world_surfacevisible)
5697 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5698 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5702 extern rtexture_t *loadingscreentexture;
5703 void gl_main_start(void)
5705 loadingscreentexture = NULL;
5706 r_texture_blanknormalmap = NULL;
5707 r_texture_white = NULL;
5708 r_texture_grey128 = NULL;
5709 r_texture_black = NULL;
5710 r_texture_whitecube = NULL;
5711 r_texture_normalizationcube = NULL;
5712 r_texture_fogattenuation = NULL;
5713 r_texture_gammaramps = NULL;
5715 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5716 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5718 switch(vid.renderpath)
5720 case RENDERPATH_GL20:
5721 case RENDERPATH_CGGL:
5722 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5723 Cvar_SetValueQuick(&gl_combine, 1);
5724 Cvar_SetValueQuick(&r_glsl, 1);
5725 r_loadnormalmap = true;
5729 case RENDERPATH_GL13:
5730 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5731 Cvar_SetValueQuick(&gl_combine, 1);
5732 Cvar_SetValueQuick(&r_glsl, 0);
5733 r_loadnormalmap = false;
5734 r_loadgloss = false;
5737 case RENDERPATH_GL11:
5738 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5739 Cvar_SetValueQuick(&gl_combine, 0);
5740 Cvar_SetValueQuick(&r_glsl, 0);
5741 r_loadnormalmap = false;
5742 r_loadgloss = false;
5748 R_FrameData_Reset();
5752 memset(r_queries, 0, sizeof(r_queries));
5754 r_qwskincache = NULL;
5755 r_qwskincache_size = 0;
5757 // set up r_skinframe loading system for textures
5758 memset(&r_skinframe, 0, sizeof(r_skinframe));
5759 r_skinframe.loadsequence = 1;
5760 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5762 r_main_texturepool = R_AllocTexturePool();
5763 R_BuildBlankTextures();
5765 if (vid.support.arb_texture_cube_map)
5768 R_BuildNormalizationCube();
5770 r_texture_fogattenuation = NULL;
5771 r_texture_gammaramps = NULL;
5772 //r_texture_fogintensity = NULL;
5773 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5774 memset(&r_waterstate, 0, sizeof(r_waterstate));
5775 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5776 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5778 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5779 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5781 memset(&r_svbsp, 0, sizeof (r_svbsp));
5783 r_refdef.fogmasktable_density = 0;
5786 void gl_main_shutdown(void)
5789 R_FrameData_Reset();
5791 R_Main_FreeViewCache();
5794 qglDeleteQueriesARB(r_maxqueries, r_queries);
5798 memset(r_queries, 0, sizeof(r_queries));
5800 r_qwskincache = NULL;
5801 r_qwskincache_size = 0;
5803 // clear out the r_skinframe state
5804 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5805 memset(&r_skinframe, 0, sizeof(r_skinframe));
5808 Mem_Free(r_svbsp.nodes);
5809 memset(&r_svbsp, 0, sizeof (r_svbsp));
5810 R_FreeTexturePool(&r_main_texturepool);
5811 loadingscreentexture = NULL;
5812 r_texture_blanknormalmap = NULL;
5813 r_texture_white = NULL;
5814 r_texture_grey128 = NULL;
5815 r_texture_black = NULL;
5816 r_texture_whitecube = NULL;
5817 r_texture_normalizationcube = NULL;
5818 r_texture_fogattenuation = NULL;
5819 r_texture_gammaramps = NULL;
5820 //r_texture_fogintensity = NULL;
5821 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5822 memset(&r_waterstate, 0, sizeof(r_waterstate));
5826 extern void CL_ParseEntityLump(char *entitystring);
5827 void gl_main_newmap(void)
5829 // FIXME: move this code to client
5831 char *entities, entname[MAX_QPATH];
5833 Mem_Free(r_qwskincache);
5834 r_qwskincache = NULL;
5835 r_qwskincache_size = 0;
5838 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5839 l = (int)strlen(entname) - 4;
5840 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5842 memcpy(entname + l, ".ent", 5);
5843 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5845 CL_ParseEntityLump(entities);
5850 if (cl.worldmodel->brush.entities)
5851 CL_ParseEntityLump(cl.worldmodel->brush.entities);
5853 R_Main_FreeViewCache();
5855 R_FrameData_Reset();
5858 void GL_Main_Init(void)
5860 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5862 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5863 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5864 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5865 if (gamemode == GAME_NEHAHRA)
5867 Cvar_RegisterVariable (&gl_fogenable);
5868 Cvar_RegisterVariable (&gl_fogdensity);
5869 Cvar_RegisterVariable (&gl_fogred);
5870 Cvar_RegisterVariable (&gl_foggreen);
5871 Cvar_RegisterVariable (&gl_fogblue);
5872 Cvar_RegisterVariable (&gl_fogstart);
5873 Cvar_RegisterVariable (&gl_fogend);
5874 Cvar_RegisterVariable (&gl_skyclip);
5876 Cvar_RegisterVariable(&r_motionblur);
5877 Cvar_RegisterVariable(&r_motionblur_maxblur);
5878 Cvar_RegisterVariable(&r_motionblur_bmin);
5879 Cvar_RegisterVariable(&r_motionblur_vmin);
5880 Cvar_RegisterVariable(&r_motionblur_vmax);
5881 Cvar_RegisterVariable(&r_motionblur_vcoeff);
5882 Cvar_RegisterVariable(&r_motionblur_randomize);
5883 Cvar_RegisterVariable(&r_damageblur);
5884 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5885 Cvar_RegisterVariable(&r_equalize_entities_minambient);
5886 Cvar_RegisterVariable(&r_equalize_entities_by);
5887 Cvar_RegisterVariable(&r_equalize_entities_to);
5888 Cvar_RegisterVariable(&r_depthfirst);
5889 Cvar_RegisterVariable(&r_useinfinitefarclip);
5890 Cvar_RegisterVariable(&r_farclip_base);
5891 Cvar_RegisterVariable(&r_farclip_world);
5892 Cvar_RegisterVariable(&r_nearclip);
5893 Cvar_RegisterVariable(&r_showbboxes);
5894 Cvar_RegisterVariable(&r_showsurfaces);
5895 Cvar_RegisterVariable(&r_showtris);
5896 Cvar_RegisterVariable(&r_shownormals);
5897 Cvar_RegisterVariable(&r_showlighting);
5898 Cvar_RegisterVariable(&r_showshadowvolumes);
5899 Cvar_RegisterVariable(&r_showcollisionbrushes);
5900 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5901 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5902 Cvar_RegisterVariable(&r_showdisabledepthtest);
5903 Cvar_RegisterVariable(&r_drawportals);
5904 Cvar_RegisterVariable(&r_drawentities);
5905 Cvar_RegisterVariable(&r_cullentities_trace);
5906 Cvar_RegisterVariable(&r_cullentities_trace_samples);
5907 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5908 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5909 Cvar_RegisterVariable(&r_cullentities_trace_delay);
5910 Cvar_RegisterVariable(&r_drawviewmodel);
5911 Cvar_RegisterVariable(&r_speeds);
5912 Cvar_RegisterVariable(&r_fullbrights);
5913 Cvar_RegisterVariable(&r_wateralpha);
5914 Cvar_RegisterVariable(&r_dynamic);
5915 Cvar_RegisterVariable(&r_fullbright);
5916 Cvar_RegisterVariable(&r_shadows);
5917 Cvar_RegisterVariable(&r_shadows_darken);
5918 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5919 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5920 Cvar_RegisterVariable(&r_shadows_throwdistance);
5921 Cvar_RegisterVariable(&r_shadows_throwdirection);
5922 Cvar_RegisterVariable(&r_q1bsp_skymasking);
5923 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5924 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5925 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5926 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5927 Cvar_RegisterVariable(&r_fog_exp2);
5928 Cvar_RegisterVariable(&r_drawfog);
5929 Cvar_RegisterVariable(&r_transparentdepthmasking);
5930 Cvar_RegisterVariable(&r_texture_dds_load);
5931 Cvar_RegisterVariable(&r_texture_dds_save);
5932 Cvar_RegisterVariable(&r_textureunits);
5933 Cvar_RegisterVariable(&gl_combine);
5934 Cvar_RegisterVariable(&r_glsl);
5935 Cvar_RegisterVariable(&r_glsl_deluxemapping);
5936 Cvar_RegisterVariable(&r_glsl_offsetmapping);
5937 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5938 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5939 Cvar_RegisterVariable(&r_glsl_postprocess);
5940 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5941 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5942 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5943 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5944 Cvar_RegisterVariable(&r_water);
5945 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5946 Cvar_RegisterVariable(&r_water_clippingplanebias);
5947 Cvar_RegisterVariable(&r_water_refractdistort);
5948 Cvar_RegisterVariable(&r_water_reflectdistort);
5949 Cvar_RegisterVariable(&r_lerpsprites);
5950 Cvar_RegisterVariable(&r_lerpmodels);
5951 Cvar_RegisterVariable(&r_lerplightstyles);
5952 Cvar_RegisterVariable(&r_waterscroll);
5953 Cvar_RegisterVariable(&r_bloom);
5954 Cvar_RegisterVariable(&r_bloom_colorscale);
5955 Cvar_RegisterVariable(&r_bloom_brighten);
5956 Cvar_RegisterVariable(&r_bloom_blur);
5957 Cvar_RegisterVariable(&r_bloom_resolution);
5958 Cvar_RegisterVariable(&r_bloom_colorexponent);
5959 Cvar_RegisterVariable(&r_bloom_colorsubtract);
5960 Cvar_RegisterVariable(&r_hdr);
5961 Cvar_RegisterVariable(&r_hdr_scenebrightness);
5962 Cvar_RegisterVariable(&r_hdr_glowintensity);
5963 Cvar_RegisterVariable(&r_hdr_range);
5964 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5965 Cvar_RegisterVariable(&developer_texturelogging);
5966 Cvar_RegisterVariable(&gl_lightmaps);
5967 Cvar_RegisterVariable(&r_test);
5968 Cvar_RegisterVariable(&r_batchmode);
5969 Cvar_RegisterVariable(&r_glsl_saturation);
5970 Cvar_RegisterVariable(&r_framedatasize);
5971 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5972 Cvar_SetValue("r_fullbrights", 0);
5973 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5975 Cvar_RegisterVariable(&r_track_sprites);
5976 Cvar_RegisterVariable(&r_track_sprites_flags);
5977 Cvar_RegisterVariable(&r_track_sprites_scalew);
5978 Cvar_RegisterVariable(&r_track_sprites_scaleh);
5981 extern void R_Textures_Init(void);
5982 extern void GL_Draw_Init(void);
5983 extern void GL_Main_Init(void);
5984 extern void R_Shadow_Init(void);
5985 extern void R_Sky_Init(void);
5986 extern void GL_Surf_Init(void);
5987 extern void R_Particles_Init(void);
5988 extern void R_Explosion_Init(void);
5989 extern void gl_backend_init(void);
5990 extern void Sbar_Init(void);
5991 extern void R_LightningBeams_Init(void);
5992 extern void Mod_RenderInit(void);
5993 extern void Font_Init(void);
5995 void Render_Init(void)
6008 R_LightningBeams_Init();
6017 extern char *ENGINE_EXTENSIONS;
6020 gl_renderer = (const char *)qglGetString(GL_RENDERER);
6021 gl_vendor = (const char *)qglGetString(GL_VENDOR);
6022 gl_version = (const char *)qglGetString(GL_VERSION);
6023 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6027 if (!gl_platformextensions)
6028 gl_platformextensions = "";
6030 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6031 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6032 Con_Printf("GL_VERSION: %s\n", gl_version);
6033 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6034 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6036 VID_CheckExtensions();
6038 // LordHavoc: report supported extensions
6039 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6041 // clear to black (loading plaque will be seen over this)
6043 qglClearColor(0,0,0,1);CHECKGLERROR
6044 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6047 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6051 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6053 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6056 p = r_refdef.view.frustum + i;
6061 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6065 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6069 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6073 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6077 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6081 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6085 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6089 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6097 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6101 for (i = 0;i < numplanes;i++)
6108 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6112 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6116 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6120 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6124 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6128 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6132 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6136 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6144 //==================================================================================
6146 // LordHavoc: this stores temporary data used within the same frame
6148 qboolean r_framedata_failed;
6149 static size_t r_framedata_size;
6150 static size_t r_framedata_current;
6151 static void *r_framedata_base;
6153 void R_FrameData_Reset(void)
6155 if (r_framedata_base)
6156 Mem_Free(r_framedata_base);
6157 r_framedata_base = NULL;
6158 r_framedata_size = 0;
6159 r_framedata_current = 0;
6160 r_framedata_failed = false;
6163 void R_FrameData_NewFrame(void)
6166 if (r_framedata_failed)
6167 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6168 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6169 wantedsize = bound(65536, wantedsize, 128*1024*1024);
6170 if (r_framedata_size != wantedsize)
6172 r_framedata_size = wantedsize;
6173 if (r_framedata_base)
6174 Mem_Free(r_framedata_base);
6175 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6177 r_framedata_current = 0;
6178 r_framedata_failed = false;
6181 void *R_FrameData_Alloc(size_t size)
6185 // align to 16 byte boundary
6186 size = (size + 15) & ~15;
6187 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6188 r_framedata_current += size;
6191 if (r_framedata_current > r_framedata_size)
6192 r_framedata_failed = true;
6194 // return NULL on everything after a failure
6195 if (r_framedata_failed)
6201 void *R_FrameData_Store(size_t size, void *data)
6203 void *d = R_FrameData_Alloc(size);
6205 memcpy(d, data, size);
6209 //==================================================================================
6211 // LordHavoc: animcache originally written by Echon, rewritten since then
6214 * Animation cache prevents re-generating mesh data for an animated model
6215 * multiple times in one frame for lighting, shadowing, reflections, etc.
6218 void R_AnimCache_Free(void)
6222 void R_AnimCache_ClearCache(void)
6225 entity_render_t *ent;
6227 for (i = 0;i < r_refdef.scene.numentities;i++)
6229 ent = r_refdef.scene.entities[i];
6230 ent->animcache_vertex3f = NULL;
6231 ent->animcache_normal3f = NULL;
6232 ent->animcache_svector3f = NULL;
6233 ent->animcache_tvector3f = NULL;
6237 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6239 dp_model_t *model = ent->model;
6241 // see if it's already cached this frame
6242 if (ent->animcache_vertex3f)
6244 // add normals/tangents if needed
6245 if (wantnormals || wanttangents)
6247 if (ent->animcache_normal3f)
6248 wantnormals = false;
6249 if (ent->animcache_svector3f)
6250 wanttangents = false;
6251 if (wantnormals || wanttangents)
6253 numvertices = model->surfmesh.num_vertices;
6255 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6258 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6259 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6261 if (!r_framedata_failed)
6262 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6268 // see if this ent is worth caching
6269 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6271 // get some memory for this entity and generate mesh data
6272 numvertices = model->surfmesh.num_vertices;
6273 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6275 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6278 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6279 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6281 if (!r_framedata_failed)
6282 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6284 return !r_framedata_failed;
6287 void R_AnimCache_CacheVisibleEntities(void)
6290 qboolean wantnormals = !r_showsurfaces.integer;
6291 qboolean wanttangents = !r_showsurfaces.integer;
6293 switch(vid.renderpath)
6295 case RENDERPATH_GL20:
6296 case RENDERPATH_CGGL:
6298 case RENDERPATH_GL13:
6299 case RENDERPATH_GL11:
6300 wanttangents = false;
6304 // TODO: thread this
6305 // NOTE: R_PrepareRTLights() also caches entities
6307 for (i = 0;i < r_refdef.scene.numentities;i++)
6308 if (r_refdef.viewcache.entityvisible[i])
6309 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6311 if (r_shadows.integer)
6312 for (i = 0;i < r_refdef.scene.numentities;i++)
6313 if (!r_refdef.viewcache.entityvisible[i])
6314 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6317 //==================================================================================
6319 static void R_View_UpdateEntityLighting (void)
6322 entity_render_t *ent;
6323 vec3_t tempdiffusenormal, avg;
6324 vec_t f, fa, fd, fdd;
6326 for (i = 0;i < r_refdef.scene.numentities;i++)
6328 ent = r_refdef.scene.entities[i];
6330 // skip unseen models
6331 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6335 if (ent->model && ent->model->brush.num_leafs)
6337 // TODO: use modellight for r_ambient settings on world?
6338 VectorSet(ent->modellight_ambient, 0, 0, 0);
6339 VectorSet(ent->modellight_diffuse, 0, 0, 0);
6340 VectorSet(ent->modellight_lightdir, 0, 0, 1);
6344 // fetch the lighting from the worldmodel data
6345 VectorClear(ent->modellight_ambient);
6346 VectorClear(ent->modellight_diffuse);
6347 VectorClear(tempdiffusenormal);
6348 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6351 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6352 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6353 if(ent->flags & RENDER_EQUALIZE)
6355 // first fix up ambient lighting...
6356 if(r_equalize_entities_minambient.value > 0)
6358 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6361 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6362 if(fa < r_equalize_entities_minambient.value * fd)
6365 // fa'/fd' = minambient
6366 // fa'+0.25*fd' = fa+0.25*fd
6368 // fa' = fd' * minambient
6369 // fd'*(0.25+minambient) = fa+0.25*fd
6371 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6372 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6374 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6375 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
6376 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6377 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6382 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6384 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6385 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6388 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6389 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6390 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6396 VectorSet(ent->modellight_ambient, 1, 1, 1);
6398 // move the light direction into modelspace coordinates for lighting code
6399 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6400 if(VectorLength2(ent->modellight_lightdir) == 0)
6401 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6402 VectorNormalize(ent->modellight_lightdir);
6406 #define MAX_LINEOFSIGHTTRACES 64
6408 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6411 vec3_t boxmins, boxmaxs;
6414 dp_model_t *model = r_refdef.scene.worldmodel;
6416 if (!model || !model->brush.TraceLineOfSight)
6419 // expand the box a little
6420 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6421 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6422 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6423 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6424 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6425 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6428 VectorCopy(eye, start);
6429 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6430 if (model->brush.TraceLineOfSight(model, start, end))
6433 // try various random positions
6434 for (i = 0;i < numsamples;i++)
6436 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6437 if (model->brush.TraceLineOfSight(model, start, end))
6445 static void R_View_UpdateEntityVisible (void)
6450 entity_render_t *ent;
6452 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6453 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6455 // worldmodel can check visibility
6456 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6457 for (i = 0;i < r_refdef.scene.numentities;i++)
6459 ent = r_refdef.scene.entities[i];
6460 if (!(ent->flags & renderimask))
6461 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)))
6462 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))
6463 r_refdef.viewcache.entityvisible[i] = true;
6465 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6467 for (i = 0;i < r_refdef.scene.numentities;i++)
6469 ent = r_refdef.scene.entities[i];
6470 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6472 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6474 continue; // temp entities do pvs only
6475 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6476 ent->last_trace_visibility = realtime;
6477 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6478 r_refdef.viewcache.entityvisible[i] = 0;
6485 // no worldmodel or it can't check visibility
6486 for (i = 0;i < r_refdef.scene.numentities;i++)
6488 ent = r_refdef.scene.entities[i];
6489 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));
6494 /// only used if skyrendermasked, and normally returns false
6495 int R_DrawBrushModelsSky (void)
6498 entity_render_t *ent;
6501 for (i = 0;i < r_refdef.scene.numentities;i++)
6503 if (!r_refdef.viewcache.entityvisible[i])
6505 ent = r_refdef.scene.entities[i];
6506 if (!ent->model || !ent->model->DrawSky)
6508 ent->model->DrawSky(ent);
6514 static void R_DrawNoModel(entity_render_t *ent);
6515 static void R_DrawModels(void)
6518 entity_render_t *ent;
6520 for (i = 0;i < r_refdef.scene.numentities;i++)
6522 if (!r_refdef.viewcache.entityvisible[i])
6524 ent = r_refdef.scene.entities[i];
6525 r_refdef.stats.entities++;
6526 if (ent->model && ent->model->Draw != NULL)
6527 ent->model->Draw(ent);
6533 static void R_DrawModelsDepth(void)
6536 entity_render_t *ent;
6538 for (i = 0;i < r_refdef.scene.numentities;i++)
6540 if (!r_refdef.viewcache.entityvisible[i])
6542 ent = r_refdef.scene.entities[i];
6543 if (ent->model && ent->model->DrawDepth != NULL)
6544 ent->model->DrawDepth(ent);
6548 static void R_DrawModelsDebug(void)
6551 entity_render_t *ent;
6553 for (i = 0;i < r_refdef.scene.numentities;i++)
6555 if (!r_refdef.viewcache.entityvisible[i])
6557 ent = r_refdef.scene.entities[i];
6558 if (ent->model && ent->model->DrawDebug != NULL)
6559 ent->model->DrawDebug(ent);
6563 static void R_DrawModelsAddWaterPlanes(void)
6566 entity_render_t *ent;
6568 for (i = 0;i < r_refdef.scene.numentities;i++)
6570 if (!r_refdef.viewcache.entityvisible[i])
6572 ent = r_refdef.scene.entities[i];
6573 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6574 ent->model->DrawAddWaterPlanes(ent);
6578 static void R_View_SetFrustum(void)
6581 double slopex, slopey;
6582 vec3_t forward, left, up, origin;
6584 // we can't trust r_refdef.view.forward and friends in reflected scenes
6585 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6588 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6589 r_refdef.view.frustum[0].normal[1] = 0 - 0;
6590 r_refdef.view.frustum[0].normal[2] = -1 - 0;
6591 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6592 r_refdef.view.frustum[1].normal[1] = 0 + 0;
6593 r_refdef.view.frustum[1].normal[2] = -1 + 0;
6594 r_refdef.view.frustum[2].normal[0] = 0 - 0;
6595 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6596 r_refdef.view.frustum[2].normal[2] = -1 - 0;
6597 r_refdef.view.frustum[3].normal[0] = 0 + 0;
6598 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6599 r_refdef.view.frustum[3].normal[2] = -1 + 0;
6603 zNear = r_refdef.nearclip;
6604 nudge = 1.0 - 1.0 / (1<<23);
6605 r_refdef.view.frustum[4].normal[0] = 0 - 0;
6606 r_refdef.view.frustum[4].normal[1] = 0 - 0;
6607 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6608 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6609 r_refdef.view.frustum[5].normal[0] = 0 + 0;
6610 r_refdef.view.frustum[5].normal[1] = 0 + 0;
6611 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6612 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6618 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6619 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6620 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6621 r_refdef.view.frustum[0].dist = m[15] - m[12];
6623 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6624 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6625 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6626 r_refdef.view.frustum[1].dist = m[15] + m[12];
6628 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6629 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6630 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6631 r_refdef.view.frustum[2].dist = m[15] - m[13];
6633 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6634 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6635 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6636 r_refdef.view.frustum[3].dist = m[15] + m[13];
6638 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6639 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6640 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6641 r_refdef.view.frustum[4].dist = m[15] - m[14];
6643 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6644 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6645 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6646 r_refdef.view.frustum[5].dist = m[15] + m[14];
6649 if (r_refdef.view.useperspective)
6651 slopex = 1.0 / r_refdef.view.frustum_x;
6652 slopey = 1.0 / r_refdef.view.frustum_y;
6653 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6654 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
6655 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
6656 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
6657 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6659 // Leaving those out was a mistake, those were in the old code, and they
6660 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6661 // I couldn't reproduce it after adding those normalizations. --blub
6662 VectorNormalize(r_refdef.view.frustum[0].normal);
6663 VectorNormalize(r_refdef.view.frustum[1].normal);
6664 VectorNormalize(r_refdef.view.frustum[2].normal);
6665 VectorNormalize(r_refdef.view.frustum[3].normal);
6667 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6668 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]);
6669 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]);
6670 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]);
6671 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]);
6673 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6674 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6675 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6676 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6677 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6681 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6682 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6683 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6684 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6685 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6686 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6687 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6688 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6689 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6690 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6692 r_refdef.view.numfrustumplanes = 5;
6694 if (r_refdef.view.useclipplane)
6696 r_refdef.view.numfrustumplanes = 6;
6697 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6700 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6701 PlaneClassify(r_refdef.view.frustum + i);
6703 // LordHavoc: note to all quake engine coders, Quake had a special case
6704 // for 90 degrees which assumed a square view (wrong), so I removed it,
6705 // Quake2 has it disabled as well.
6707 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6708 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6709 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6710 //PlaneClassify(&frustum[0]);
6712 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6713 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6714 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6715 //PlaneClassify(&frustum[1]);
6717 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6718 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6719 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6720 //PlaneClassify(&frustum[2]);
6722 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6723 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6724 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6725 //PlaneClassify(&frustum[3]);
6728 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6729 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6730 //PlaneClassify(&frustum[4]);
6733 void R_View_Update(void)
6735 R_Main_ResizeViewCache();
6736 R_View_SetFrustum();
6737 R_View_WorldVisibility(r_refdef.view.useclipplane);
6738 R_View_UpdateEntityVisible();
6739 R_View_UpdateEntityLighting();
6742 void R_SetupView(qboolean allowwaterclippingplane)
6744 const float *customclipplane = NULL;
6746 if (r_refdef.view.useclipplane && allowwaterclippingplane)
6748 // LordHavoc: couldn't figure out how to make this approach the
6749 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6750 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6751 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6752 dist = r_refdef.view.clipplane.dist;
6753 plane[0] = r_refdef.view.clipplane.normal[0];
6754 plane[1] = r_refdef.view.clipplane.normal[1];
6755 plane[2] = r_refdef.view.clipplane.normal[2];
6757 customclipplane = plane;
6760 if (!r_refdef.view.useperspective)
6761 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);
6762 else if (vid.stencil && r_useinfinitefarclip.integer)
6763 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);
6765 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);
6766 R_SetViewport(&r_refdef.view.viewport);
6769 void R_EntityMatrix(const matrix4x4_t *matrix)
6771 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6773 gl_modelmatrixchanged = false;
6774 gl_modelmatrix = *matrix;
6775 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6776 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6777 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6778 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6780 switch(vid.renderpath)
6782 case RENDERPATH_GL20:
6783 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6784 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6785 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6787 case RENDERPATH_CGGL:
6790 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6791 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6792 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6795 case RENDERPATH_GL13:
6796 case RENDERPATH_GL11:
6797 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6803 void R_ResetViewRendering2D(void)
6805 r_viewport_t viewport;
6808 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6809 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);
6810 R_SetViewport(&viewport);
6811 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6812 GL_Color(1, 1, 1, 1);
6813 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6814 GL_BlendFunc(GL_ONE, GL_ZERO);
6815 GL_AlphaTest(false);
6816 GL_ScissorTest(false);
6817 GL_DepthMask(false);
6818 GL_DepthRange(0, 1);
6819 GL_DepthTest(false);
6820 R_EntityMatrix(&identitymatrix);
6821 R_Mesh_ResetTextureState();
6822 GL_PolygonOffset(0, 0);
6823 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6824 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6825 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6826 qglStencilMask(~0);CHECKGLERROR
6827 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6828 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6829 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6832 void R_ResetViewRendering3D(void)
6837 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6838 GL_Color(1, 1, 1, 1);
6839 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6840 GL_BlendFunc(GL_ONE, GL_ZERO);
6841 GL_AlphaTest(false);
6842 GL_ScissorTest(true);
6844 GL_DepthRange(0, 1);
6846 R_EntityMatrix(&identitymatrix);
6847 R_Mesh_ResetTextureState();
6848 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6849 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6850 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6851 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6852 qglStencilMask(~0);CHECKGLERROR
6853 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6854 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6855 GL_CullFace(r_refdef.view.cullface_back);
6858 void R_RenderScene(void);
6859 void R_RenderWaterPlanes(void);
6861 static void R_Water_StartFrame(void)
6864 int waterwidth, waterheight, texturewidth, textureheight;
6865 r_waterstate_waterplane_t *p;
6867 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6870 switch(vid.renderpath)
6872 case RENDERPATH_GL20:
6873 case RENDERPATH_CGGL:
6875 case RENDERPATH_GL13:
6876 case RENDERPATH_GL11:
6880 // set waterwidth and waterheight to the water resolution that will be
6881 // used (often less than the screen resolution for faster rendering)
6882 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6883 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6885 // calculate desired texture sizes
6886 // can't use water if the card does not support the texture size
6887 if (!r_water.integer || r_showsurfaces.integer)
6888 texturewidth = textureheight = waterwidth = waterheight = 0;
6889 else if (vid.support.arb_texture_non_power_of_two)
6891 texturewidth = waterwidth;
6892 textureheight = waterheight;
6896 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
6897 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
6900 // allocate textures as needed
6901 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6903 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6904 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6906 if (p->texture_refraction)
6907 R_FreeTexture(p->texture_refraction);
6908 p->texture_refraction = NULL;
6909 if (p->texture_reflection)
6910 R_FreeTexture(p->texture_reflection);
6911 p->texture_reflection = NULL;
6913 memset(&r_waterstate, 0, sizeof(r_waterstate));
6914 r_waterstate.texturewidth = texturewidth;
6915 r_waterstate.textureheight = textureheight;
6918 if (r_waterstate.texturewidth)
6920 r_waterstate.enabled = true;
6922 // when doing a reduced render (HDR) we want to use a smaller area
6923 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6924 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6926 // set up variables that will be used in shader setup
6927 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6928 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6929 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6930 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6933 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6934 r_waterstate.numwaterplanes = 0;
6937 void R_Water_AddWaterPlane(msurface_t *surface)
6939 int triangleindex, planeindex;
6945 r_waterstate_waterplane_t *p;
6946 texture_t *t = R_GetCurrentTexture(surface->texture);
6947 // just use the first triangle with a valid normal for any decisions
6948 VectorClear(normal);
6949 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6951 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6952 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6953 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6954 TriangleNormal(vert[0], vert[1], vert[2], normal);
6955 if (VectorLength2(normal) >= 0.001)
6959 VectorCopy(normal, plane.normal);
6960 VectorNormalize(plane.normal);
6961 plane.dist = DotProduct(vert[0], plane.normal);
6962 PlaneClassify(&plane);
6963 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6965 // skip backfaces (except if nocullface is set)
6966 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6968 VectorNegate(plane.normal, plane.normal);
6970 PlaneClassify(&plane);
6974 // find a matching plane if there is one
6975 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6976 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6978 if (planeindex >= r_waterstate.maxwaterplanes)
6979 return; // nothing we can do, out of planes
6981 // if this triangle does not fit any known plane rendered this frame, add one
6982 if (planeindex >= r_waterstate.numwaterplanes)
6984 // store the new plane
6985 r_waterstate.numwaterplanes++;
6987 // clear materialflags and pvs
6988 p->materialflags = 0;
6989 p->pvsvalid = false;
6991 // merge this surface's materialflags into the waterplane
6992 p->materialflags |= t->currentmaterialflags;
6993 // merge this surface's PVS into the waterplane
6994 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6995 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6996 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6998 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7003 static void R_Water_ProcessPlanes(void)
7005 r_refdef_view_t originalview;
7006 r_refdef_view_t myview;
7008 r_waterstate_waterplane_t *p;
7010 originalview = r_refdef.view;
7012 // make sure enough textures are allocated
7013 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7015 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7017 if (!p->texture_refraction)
7018 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7019 if (!p->texture_refraction)
7023 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7025 if (!p->texture_reflection)
7026 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7027 if (!p->texture_reflection)
7033 r_refdef.view = originalview;
7034 r_refdef.view.showdebug = false;
7035 r_refdef.view.width = r_waterstate.waterwidth;
7036 r_refdef.view.height = r_waterstate.waterheight;
7037 r_refdef.view.useclipplane = true;
7038 myview = r_refdef.view;
7039 r_waterstate.renderingscene = true;
7040 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7042 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7044 r_refdef.view = myview;
7045 // render reflected scene and copy into texture
7046 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7047 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7048 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7049 r_refdef.view.clipplane = p->plane;
7050 // reverse the cullface settings for this render
7051 r_refdef.view.cullface_front = GL_FRONT;
7052 r_refdef.view.cullface_back = GL_BACK;
7053 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7055 r_refdef.view.usecustompvs = true;
7057 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7059 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7062 R_ResetViewRendering3D();
7063 R_ClearScreen(r_refdef.fogenabled);
7067 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);
7070 // render the normal view scene and copy into texture
7071 // (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)
7072 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7074 r_refdef.view = myview;
7075 r_refdef.view.clipplane = p->plane;
7076 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7077 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7078 PlaneClassify(&r_refdef.view.clipplane);
7080 R_ResetViewRendering3D();
7081 R_ClearScreen(r_refdef.fogenabled);
7085 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);
7089 r_waterstate.renderingscene = false;
7090 r_refdef.view = originalview;
7091 R_ResetViewRendering3D();
7092 R_ClearScreen(r_refdef.fogenabled);
7096 r_refdef.view = originalview;
7097 r_waterstate.renderingscene = false;
7098 Cvar_SetValueQuick(&r_water, 0);
7099 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
7103 void R_Bloom_StartFrame(void)
7105 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7107 switch(vid.renderpath)
7109 case RENDERPATH_GL20:
7110 case RENDERPATH_CGGL:
7112 case RENDERPATH_GL13:
7113 case RENDERPATH_GL11:
7117 // set bloomwidth and bloomheight to the bloom resolution that will be
7118 // used (often less than the screen resolution for faster rendering)
7119 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7120 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7121 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7122 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7123 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7125 // calculate desired texture sizes
7126 if (vid.support.arb_texture_non_power_of_two)
7128 screentexturewidth = r_refdef.view.width;
7129 screentextureheight = r_refdef.view.height;
7130 bloomtexturewidth = r_bloomstate.bloomwidth;
7131 bloomtextureheight = r_bloomstate.bloomheight;
7135 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
7136 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
7137 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
7138 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
7141 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))
7143 Cvar_SetValueQuick(&r_hdr, 0);
7144 Cvar_SetValueQuick(&r_bloom, 0);
7145 Cvar_SetValueQuick(&r_motionblur, 0);
7146 Cvar_SetValueQuick(&r_damageblur, 0);
7149 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)))
7150 screentexturewidth = screentextureheight = 0;
7151 if (!r_hdr.integer && !r_bloom.integer)
7152 bloomtexturewidth = bloomtextureheight = 0;
7154 // allocate textures as needed
7155 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7157 if (r_bloomstate.texture_screen)
7158 R_FreeTexture(r_bloomstate.texture_screen);
7159 r_bloomstate.texture_screen = NULL;
7160 r_bloomstate.screentexturewidth = screentexturewidth;
7161 r_bloomstate.screentextureheight = screentextureheight;
7162 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7163 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7165 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7167 if (r_bloomstate.texture_bloom)
7168 R_FreeTexture(r_bloomstate.texture_bloom);
7169 r_bloomstate.texture_bloom = NULL;
7170 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7171 r_bloomstate.bloomtextureheight = bloomtextureheight;
7172 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7173 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7176 // when doing a reduced render (HDR) we want to use a smaller area
7177 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7178 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7179 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7180 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7181 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7183 // set up a texcoord array for the full resolution screen image
7184 // (we have to keep this around to copy back during final render)
7185 r_bloomstate.screentexcoord2f[0] = 0;
7186 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7187 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7188 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7189 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7190 r_bloomstate.screentexcoord2f[5] = 0;
7191 r_bloomstate.screentexcoord2f[6] = 0;
7192 r_bloomstate.screentexcoord2f[7] = 0;
7194 // set up a texcoord array for the reduced resolution bloom image
7195 // (which will be additive blended over the screen image)
7196 r_bloomstate.bloomtexcoord2f[0] = 0;
7197 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7198 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7199 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7200 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7201 r_bloomstate.bloomtexcoord2f[5] = 0;
7202 r_bloomstate.bloomtexcoord2f[6] = 0;
7203 r_bloomstate.bloomtexcoord2f[7] = 0;
7205 if (r_hdr.integer || r_bloom.integer)
7207 r_bloomstate.enabled = true;
7208 r_bloomstate.hdr = r_hdr.integer != 0;
7211 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);
7214 void R_Bloom_CopyBloomTexture(float colorscale)
7216 r_refdef.stats.bloom++;
7218 // scale down screen texture to the bloom texture size
7220 R_SetViewport(&r_bloomstate.viewport);
7221 GL_BlendFunc(GL_ONE, GL_ZERO);
7222 GL_Color(colorscale, colorscale, colorscale, 1);
7223 // TODO: optimize with multitexture or GLSL
7224 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7225 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7226 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7227 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7229 // we now have a bloom image in the framebuffer
7230 // copy it into the bloom image texture for later processing
7231 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);
7232 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7235 void R_Bloom_CopyHDRTexture(void)
7237 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);
7238 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7241 void R_Bloom_MakeTexture(void)
7244 float xoffset, yoffset, r, brighten;
7246 r_refdef.stats.bloom++;
7248 R_ResetViewRendering2D();
7249 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7250 R_Mesh_ColorPointer(NULL, 0, 0);
7252 // we have a bloom image in the framebuffer
7254 R_SetViewport(&r_bloomstate.viewport);
7256 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7259 r = bound(0, r_bloom_colorexponent.value / x, 1);
7260 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7261 GL_Color(r, r, r, 1);
7262 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7263 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7264 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7265 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7267 // copy the vertically blurred bloom view to a texture
7268 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);
7269 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7272 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7273 brighten = r_bloom_brighten.value;
7275 brighten *= r_hdr_range.value;
7276 brighten = sqrt(brighten);
7278 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7279 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7280 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7282 for (dir = 0;dir < 2;dir++)
7284 // blend on at multiple vertical offsets to achieve a vertical blur
7285 // TODO: do offset blends using GLSL
7286 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7287 GL_BlendFunc(GL_ONE, GL_ZERO);
7288 for (x = -range;x <= range;x++)
7290 if (!dir){xoffset = 0;yoffset = x;}
7291 else {xoffset = x;yoffset = 0;}
7292 xoffset /= (float)r_bloomstate.bloomtexturewidth;
7293 yoffset /= (float)r_bloomstate.bloomtextureheight;
7294 // compute a texcoord array with the specified x and y offset
7295 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7296 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7297 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7298 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7299 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7300 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7301 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7302 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7303 // this r value looks like a 'dot' particle, fading sharply to
7304 // black at the edges
7305 // (probably not realistic but looks good enough)
7306 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7307 //r = brighten/(range*2+1);
7308 r = brighten / (range * 2 + 1);
7310 r *= (1 - x*x/(float)(range*range));
7311 GL_Color(r, r, r, 1);
7312 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7313 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7314 GL_BlendFunc(GL_ONE, GL_ONE);
7317 // copy the vertically blurred bloom view to a texture
7318 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);
7319 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7322 // apply subtract last
7323 // (just like it would be in a GLSL shader)
7324 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7326 GL_BlendFunc(GL_ONE, GL_ZERO);
7327 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7328 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7329 GL_Color(1, 1, 1, 1);
7330 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7331 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7333 GL_BlendFunc(GL_ONE, GL_ONE);
7334 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7335 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7336 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7337 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7338 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7339 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7340 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7342 // copy the darkened bloom view to a texture
7343 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);
7344 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7348 void R_HDR_RenderBloomTexture(void)
7350 int oldwidth, oldheight;
7351 float oldcolorscale;
7353 oldcolorscale = r_refdef.view.colorscale;
7354 oldwidth = r_refdef.view.width;
7355 oldheight = r_refdef.view.height;
7356 r_refdef.view.width = r_bloomstate.bloomwidth;
7357 r_refdef.view.height = r_bloomstate.bloomheight;
7359 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
7360 // TODO: add exposure compensation features
7361 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7363 r_refdef.view.showdebug = false;
7364 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7366 R_ResetViewRendering3D();
7368 R_ClearScreen(r_refdef.fogenabled);
7369 if (r_timereport_active)
7370 R_TimeReport("HDRclear");
7373 if (r_timereport_active)
7374 R_TimeReport("visibility");
7376 // only do secondary renders with HDR if r_hdr is 2 or higher
7377 r_waterstate.numwaterplanes = 0;
7378 if (r_waterstate.enabled && r_hdr.integer >= 2)
7379 R_RenderWaterPlanes();
7381 r_refdef.view.showdebug = true;
7383 r_waterstate.numwaterplanes = 0;
7385 R_ResetViewRendering2D();
7387 R_Bloom_CopyHDRTexture();
7388 R_Bloom_MakeTexture();
7390 // restore the view settings
7391 r_refdef.view.width = oldwidth;
7392 r_refdef.view.height = oldheight;
7393 r_refdef.view.colorscale = oldcolorscale;
7395 R_ResetViewRendering3D();
7397 R_ClearScreen(r_refdef.fogenabled);
7398 if (r_timereport_active)
7399 R_TimeReport("viewclear");
7402 static void R_BlendView(void)
7404 unsigned int permutation;
7405 float uservecs[4][4];
7407 switch (vid.renderpath)
7409 case RENDERPATH_GL20:
7410 case RENDERPATH_CGGL:
7412 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7413 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7414 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7415 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7416 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7418 if (r_bloomstate.texture_screen)
7420 // make sure the buffer is available
7421 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7423 R_ResetViewRendering2D();
7424 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7425 R_Mesh_ColorPointer(NULL, 0, 0);
7427 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7429 // declare variables
7431 static float avgspeed;
7433 speed = VectorLength(cl.movement_velocity);
7435 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7436 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7438 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7439 speed = bound(0, speed, 1);
7440 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7442 // calculate values into a standard alpha
7443 cl.motionbluralpha = 1 - exp(-
7445 (r_motionblur.value * speed / 80)
7447 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7450 max(0.0001, cl.time - cl.oldtime) // fps independent
7453 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7454 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7456 if (cl.motionbluralpha > 0)
7458 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7459 GL_Color(1, 1, 1, cl.motionbluralpha);
7460 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7461 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7462 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7463 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7467 // copy view into the screen texture
7468 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);
7469 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7471 else if (!r_bloomstate.texture_bloom)
7473 // we may still have to do view tint...
7474 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7476 // apply a color tint to the whole view
7477 R_ResetViewRendering2D();
7478 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7479 R_Mesh_ColorPointer(NULL, 0, 0);
7480 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7481 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7482 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7483 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7485 break; // no screen processing, no bloom, skip it
7488 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7490 // render simple bloom effect
7491 // copy the screen and shrink it and darken it for the bloom process
7492 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7493 // make the bloom texture
7494 R_Bloom_MakeTexture();
7497 #if _MSC_VER >= 1400
7498 #define sscanf sscanf_s
7500 memset(uservecs, 0, sizeof(uservecs));
7501 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7502 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7503 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7504 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7506 R_ResetViewRendering2D();
7507 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7508 R_Mesh_ColorPointer(NULL, 0, 0);
7509 GL_Color(1, 1, 1, 1);
7510 GL_BlendFunc(GL_ONE, GL_ZERO);
7511 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7512 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7514 switch(vid.renderpath)
7516 case RENDERPATH_GL20:
7517 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7518 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
7519 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
7520 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7521 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]);
7522 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime , cl.time);
7523 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7524 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]);
7525 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]);
7526 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]);
7527 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]);
7528 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7529 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7531 case RENDERPATH_CGGL:
7533 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7534 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
7535 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
7536 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
7537 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
7538 if (r_cg_permutation->fp_ClientTime ) cgGLSetParameter1f( r_cg_permutation->fp_ClientTime , cl.time);CHECKCGERROR
7539 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7540 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
7541 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
7542 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
7543 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
7544 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
7545 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7551 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7552 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7554 case RENDERPATH_GL13:
7555 case RENDERPATH_GL11:
7556 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7558 // apply a color tint to the whole view
7559 R_ResetViewRendering2D();
7560 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7561 R_Mesh_ColorPointer(NULL, 0, 0);
7562 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7563 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7564 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7565 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7571 matrix4x4_t r_waterscrollmatrix;
7573 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7575 if (r_refdef.fog_density)
7577 r_refdef.fogcolor[0] = r_refdef.fog_red;
7578 r_refdef.fogcolor[1] = r_refdef.fog_green;
7579 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7581 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7582 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7583 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7584 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7588 VectorCopy(r_refdef.fogcolor, fogvec);
7589 // color.rgb *= ContrastBoost * SceneBrightness;
7590 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7591 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7592 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7593 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7598 void R_UpdateVariables(void)
7602 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7604 r_refdef.farclip = r_farclip_base.value;
7605 if (r_refdef.scene.worldmodel)
7606 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7607 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7609 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7610 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7611 r_refdef.polygonfactor = 0;
7612 r_refdef.polygonoffset = 0;
7613 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7614 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7616 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7617 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7618 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7619 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7620 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7621 if (r_showsurfaces.integer)
7623 r_refdef.scene.rtworld = false;
7624 r_refdef.scene.rtworldshadows = false;
7625 r_refdef.scene.rtdlight = false;
7626 r_refdef.scene.rtdlightshadows = false;
7627 r_refdef.lightmapintensity = 0;
7630 if (gamemode == GAME_NEHAHRA)
7632 if (gl_fogenable.integer)
7634 r_refdef.oldgl_fogenable = true;
7635 r_refdef.fog_density = gl_fogdensity.value;
7636 r_refdef.fog_red = gl_fogred.value;
7637 r_refdef.fog_green = gl_foggreen.value;
7638 r_refdef.fog_blue = gl_fogblue.value;
7639 r_refdef.fog_alpha = 1;
7640 r_refdef.fog_start = 0;
7641 r_refdef.fog_end = gl_skyclip.value;
7642 r_refdef.fog_height = 1<<30;
7643 r_refdef.fog_fadedepth = 128;
7645 else if (r_refdef.oldgl_fogenable)
7647 r_refdef.oldgl_fogenable = false;
7648 r_refdef.fog_density = 0;
7649 r_refdef.fog_red = 0;
7650 r_refdef.fog_green = 0;
7651 r_refdef.fog_blue = 0;
7652 r_refdef.fog_alpha = 0;
7653 r_refdef.fog_start = 0;
7654 r_refdef.fog_end = 0;
7655 r_refdef.fog_height = 1<<30;
7656 r_refdef.fog_fadedepth = 128;
7660 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7661 r_refdef.fog_start = max(0, r_refdef.fog_start);
7662 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7664 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7666 if (r_refdef.fog_density && r_drawfog.integer)
7668 r_refdef.fogenabled = true;
7669 // this is the point where the fog reaches 0.9986 alpha, which we
7670 // consider a good enough cutoff point for the texture
7671 // (0.9986 * 256 == 255.6)
7672 if (r_fog_exp2.integer)
7673 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7675 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7676 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7677 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7678 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7679 // fog color was already set
7680 // update the fog texture
7681 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)
7682 R_BuildFogTexture();
7685 r_refdef.fogenabled = false;
7687 switch(vid.renderpath)
7689 case RENDERPATH_GL20:
7690 case RENDERPATH_CGGL:
7691 if(v_glslgamma.integer && !vid_gammatables_trivial)
7693 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7695 // build GLSL gamma texture
7696 #define RAMPWIDTH 256
7697 unsigned short ramp[RAMPWIDTH * 3];
7698 unsigned char rampbgr[RAMPWIDTH][4];
7701 r_texture_gammaramps_serial = vid_gammatables_serial;
7703 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7704 for(i = 0; i < RAMPWIDTH; ++i)
7706 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7707 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7708 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7711 if (r_texture_gammaramps)
7713 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7717 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);
7723 // remove GLSL gamma texture
7726 case RENDERPATH_GL13:
7727 case RENDERPATH_GL11:
7732 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7733 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7739 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7740 if( scenetype != r_currentscenetype ) {
7741 // store the old scenetype
7742 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7743 r_currentscenetype = scenetype;
7744 // move in the new scene
7745 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7754 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7756 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7757 if( scenetype == r_currentscenetype ) {
7758 return &r_refdef.scene;
7760 return &r_scenes_store[ scenetype ];
7769 void R_RenderView(void)
7771 if (r_timereport_active)
7772 R_TimeReport("start");
7773 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7775 if (!r_drawentities.integer)
7776 r_refdef.scene.numentities = 0;
7778 R_AnimCache_ClearCache();
7779 R_FrameData_NewFrame();
7781 if (r_refdef.view.isoverlay)
7783 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7784 GL_Clear( GL_DEPTH_BUFFER_BIT );
7785 R_TimeReport("depthclear");
7787 r_refdef.view.showdebug = false;
7789 r_waterstate.enabled = false;
7790 r_waterstate.numwaterplanes = 0;
7798 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7799 return; //Host_Error ("R_RenderView: NULL worldmodel");
7801 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7803 // break apart the view matrix into vectors for various purposes
7804 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7805 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7806 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7807 VectorNegate(r_refdef.view.left, r_refdef.view.right);
7808 // make an inverted copy of the view matrix for tracking sprites
7809 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7811 R_Shadow_UpdateWorldLightSelection();
7813 R_Bloom_StartFrame();
7814 R_Water_StartFrame();
7817 if (r_timereport_active)
7818 R_TimeReport("viewsetup");
7820 R_ResetViewRendering3D();
7822 if (r_refdef.view.clear || r_refdef.fogenabled)
7824 R_ClearScreen(r_refdef.fogenabled);
7825 if (r_timereport_active)
7826 R_TimeReport("viewclear");
7828 r_refdef.view.clear = true;
7830 // this produces a bloom texture to be used in R_BlendView() later
7831 if (r_hdr.integer && r_bloomstate.bloomwidth)
7832 R_HDR_RenderBloomTexture();
7834 r_refdef.view.showdebug = true;
7837 if (r_timereport_active)
7838 R_TimeReport("visibility");
7840 r_waterstate.numwaterplanes = 0;
7841 if (r_waterstate.enabled)
7842 R_RenderWaterPlanes();
7845 r_waterstate.numwaterplanes = 0;
7848 if (r_timereport_active)
7849 R_TimeReport("blendview");
7851 GL_Scissor(0, 0, vid.width, vid.height);
7852 GL_ScissorTest(false);
7856 void R_RenderWaterPlanes(void)
7858 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7860 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7861 if (r_timereport_active)
7862 R_TimeReport("waterworld");
7865 // don't let sound skip if going slow
7866 if (r_refdef.scene.extraupdate)
7869 R_DrawModelsAddWaterPlanes();
7870 if (r_timereport_active)
7871 R_TimeReport("watermodels");
7873 if (r_waterstate.numwaterplanes)
7875 R_Water_ProcessPlanes();
7876 if (r_timereport_active)
7877 R_TimeReport("waterscenes");
7881 extern void R_DrawLightningBeams (void);
7882 extern void VM_CL_AddPolygonsToMeshQueue (void);
7883 extern void R_DrawPortals (void);
7884 extern cvar_t cl_locs_show;
7885 static void R_DrawLocs(void);
7886 static void R_DrawEntityBBoxes(void);
7887 static void R_DrawModelDecals(void);
7888 extern cvar_t cl_decals_newsystem;
7889 extern qboolean r_shadow_usingdeferredprepass;
7890 void R_RenderScene(void)
7892 r_refdef.stats.renders++;
7893 r_textureframe++; // used only by R_GetCurrentTexture
7897 // don't let sound skip if going slow
7898 if (r_refdef.scene.extraupdate)
7901 R_MeshQueue_BeginScene();
7905 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);
7907 if (cl.csqc_vidvars.drawworld)
7909 // don't let sound skip if going slow
7910 if (r_refdef.scene.extraupdate)
7913 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7915 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7916 if (r_timereport_active)
7917 R_TimeReport("worldsky");
7920 if (R_DrawBrushModelsSky() && r_timereport_active)
7921 R_TimeReport("bmodelsky");
7923 if (skyrendermasked && skyrenderlater)
7925 // we have to force off the water clipping plane while rendering sky
7929 if (r_timereport_active)
7930 R_TimeReport("sky");
7934 R_AnimCache_CacheVisibleEntities();
7935 if (r_timereport_active)
7936 R_TimeReport("animation");
7938 R_Shadow_PrepareLights();
7939 if (r_timereport_active)
7940 R_TimeReport("preparelights");
7942 if (r_shadow_usingdeferredprepass)
7943 R_Shadow_DrawPrepass();
7945 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7947 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7948 if (r_timereport_active)
7949 R_TimeReport("worlddepth");
7951 if (r_depthfirst.integer >= 2)
7953 R_DrawModelsDepth();
7954 if (r_timereport_active)
7955 R_TimeReport("modeldepth");
7958 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7960 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7961 if (r_timereport_active)
7962 R_TimeReport("world");
7965 // don't let sound skip if going slow
7966 if (r_refdef.scene.extraupdate)
7970 if (r_timereport_active)
7971 R_TimeReport("models");
7973 // don't let sound skip if going slow
7974 if (r_refdef.scene.extraupdate)
7977 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7979 R_DrawModelShadows();
7980 R_ResetViewRendering3D();
7981 // don't let sound skip if going slow
7982 if (r_refdef.scene.extraupdate)
7986 if (!r_shadow_usingdeferredprepass)
7988 R_Shadow_DrawLights();
7989 if (r_timereport_active)
7990 R_TimeReport("rtlights");
7993 // don't let sound skip if going slow
7994 if (r_refdef.scene.extraupdate)
7997 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7999 R_DrawModelShadows();
8000 R_ResetViewRendering3D();
8001 // don't let sound skip if going slow
8002 if (r_refdef.scene.extraupdate)
8006 if (cl.csqc_vidvars.drawworld)
8008 if (cl_decals_newsystem.integer)
8010 R_DrawModelDecals();
8011 if (r_timereport_active)
8012 R_TimeReport("modeldecals");
8017 if (r_timereport_active)
8018 R_TimeReport("decals");
8022 if (r_timereport_active)
8023 R_TimeReport("particles");
8026 if (r_timereport_active)
8027 R_TimeReport("explosions");
8029 R_DrawLightningBeams();
8030 if (r_timereport_active)
8031 R_TimeReport("lightning");
8034 VM_CL_AddPolygonsToMeshQueue();
8036 if (r_refdef.view.showdebug)
8038 if (cl_locs_show.integer)
8041 if (r_timereport_active)
8042 R_TimeReport("showlocs");
8045 if (r_drawportals.integer)
8048 if (r_timereport_active)
8049 R_TimeReport("portals");
8052 if (r_showbboxes.value > 0)
8054 R_DrawEntityBBoxes();
8055 if (r_timereport_active)
8056 R_TimeReport("bboxes");
8060 R_MeshQueue_RenderTransparent();
8061 if (r_timereport_active)
8062 R_TimeReport("drawtrans");
8064 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))
8066 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8067 if (r_timereport_active)
8068 R_TimeReport("worlddebug");
8069 R_DrawModelsDebug();
8070 if (r_timereport_active)
8071 R_TimeReport("modeldebug");
8074 if (cl.csqc_vidvars.drawworld)
8076 R_Shadow_DrawCoronas();
8077 if (r_timereport_active)
8078 R_TimeReport("coronas");
8081 // don't let sound skip if going slow
8082 if (r_refdef.scene.extraupdate)
8085 R_ResetViewRendering2D();
8088 static const unsigned short bboxelements[36] =
8098 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8101 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8103 RSurf_ActiveWorldEntity();
8105 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8106 GL_DepthMask(false);
8107 GL_DepthRange(0, 1);
8108 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8109 R_Mesh_ResetTextureState();
8111 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8112 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8113 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8114 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8115 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8116 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8117 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8118 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8119 R_FillColors(color4f, 8, cr, cg, cb, ca);
8120 if (r_refdef.fogenabled)
8122 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8124 f1 = RSurf_FogVertex(v);
8126 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8127 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8128 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8131 R_Mesh_VertexPointer(vertex3f, 0, 0);
8132 R_Mesh_ColorPointer(color4f, 0, 0);
8133 R_Mesh_ResetTextureState();
8134 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8135 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8138 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8142 prvm_edict_t *edict;
8143 prvm_prog_t *prog_save = prog;
8145 // this function draws bounding boxes of server entities
8149 GL_CullFace(GL_NONE);
8150 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8154 for (i = 0;i < numsurfaces;i++)
8156 edict = PRVM_EDICT_NUM(surfacelist[i]);
8157 switch ((int)edict->fields.server->solid)
8159 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
8160 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
8161 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
8162 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8163 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
8164 default: Vector4Set(color, 0, 0, 0, 0.50);break;
8166 color[3] *= r_showbboxes.value;
8167 color[3] = bound(0, color[3], 1);
8168 GL_DepthTest(!r_showdisabledepthtest.integer);
8169 GL_CullFace(r_refdef.view.cullface_front);
8170 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8176 static void R_DrawEntityBBoxes(void)
8179 prvm_edict_t *edict;
8181 prvm_prog_t *prog_save = prog;
8183 // this function draws bounding boxes of server entities
8189 for (i = 0;i < prog->num_edicts;i++)
8191 edict = PRVM_EDICT_NUM(i);
8192 if (edict->priv.server->free)
8194 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8195 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8197 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8199 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8200 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8206 static const int nomodelelement3i[24] =
8218 static const unsigned short nomodelelement3s[24] =
8230 static const float nomodelvertex3f[6*3] =
8240 static const float nomodelcolor4f[6*4] =
8242 0.0f, 0.0f, 0.5f, 1.0f,
8243 0.0f, 0.0f, 0.5f, 1.0f,
8244 0.0f, 0.5f, 0.0f, 1.0f,
8245 0.0f, 0.5f, 0.0f, 1.0f,
8246 0.5f, 0.0f, 0.0f, 1.0f,
8247 0.5f, 0.0f, 0.0f, 1.0f
8250 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8256 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);
8258 // this is only called once per entity so numsurfaces is always 1, and
8259 // surfacelist is always {0}, so this code does not handle batches
8261 if (rsurface.ent_flags & RENDER_ADDITIVE)
8263 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8264 GL_DepthMask(false);
8266 else if (rsurface.colormod[3] < 1)
8268 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8269 GL_DepthMask(false);
8273 GL_BlendFunc(GL_ONE, GL_ZERO);
8276 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8277 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8278 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8279 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8280 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8281 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8282 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8283 R_Mesh_ColorPointer(color4f, 0, 0);
8284 for (i = 0, c = color4f;i < 6;i++, c += 4)
8286 c[0] *= rsurface.colormod[0];
8287 c[1] *= rsurface.colormod[1];
8288 c[2] *= rsurface.colormod[2];
8289 c[3] *= rsurface.colormod[3];
8291 if (r_refdef.fogenabled)
8293 for (i = 0, c = color4f;i < 6;i++, c += 4)
8295 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8297 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8298 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8299 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8302 R_Mesh_ResetTextureState();
8303 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8306 void R_DrawNoModel(entity_render_t *ent)
8309 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8310 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8311 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8313 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8316 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8318 vec3_t right1, right2, diff, normal;
8320 VectorSubtract (org2, org1, normal);
8322 // calculate 'right' vector for start
8323 VectorSubtract (r_refdef.view.origin, org1, diff);
8324 CrossProduct (normal, diff, right1);
8325 VectorNormalize (right1);
8327 // calculate 'right' vector for end
8328 VectorSubtract (r_refdef.view.origin, org2, diff);
8329 CrossProduct (normal, diff, right2);
8330 VectorNormalize (right2);
8332 vert[ 0] = org1[0] + width * right1[0];
8333 vert[ 1] = org1[1] + width * right1[1];
8334 vert[ 2] = org1[2] + width * right1[2];
8335 vert[ 3] = org1[0] - width * right1[0];
8336 vert[ 4] = org1[1] - width * right1[1];
8337 vert[ 5] = org1[2] - width * right1[2];
8338 vert[ 6] = org2[0] - width * right2[0];
8339 vert[ 7] = org2[1] - width * right2[1];
8340 vert[ 8] = org2[2] - width * right2[2];
8341 vert[ 9] = org2[0] + width * right2[0];
8342 vert[10] = org2[1] + width * right2[1];
8343 vert[11] = org2[2] + width * right2[2];
8346 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)
8348 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8349 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8350 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8351 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8352 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8353 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8354 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8355 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8356 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8357 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8358 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8359 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8362 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8367 VectorSet(v, x, y, z);
8368 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8369 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8371 if (i == mesh->numvertices)
8373 if (mesh->numvertices < mesh->maxvertices)
8375 VectorCopy(v, vertex3f);
8376 mesh->numvertices++;
8378 return mesh->numvertices;
8384 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8388 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8389 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8390 e = mesh->element3i + mesh->numtriangles * 3;
8391 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8393 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8394 if (mesh->numtriangles < mesh->maxtriangles)
8399 mesh->numtriangles++;
8401 element[1] = element[2];
8405 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8409 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8410 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8411 e = mesh->element3i + mesh->numtriangles * 3;
8412 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8414 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8415 if (mesh->numtriangles < mesh->maxtriangles)
8420 mesh->numtriangles++;
8422 element[1] = element[2];
8426 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8427 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8429 int planenum, planenum2;
8432 mplane_t *plane, *plane2;
8434 double temppoints[2][256*3];
8435 // figure out how large a bounding box we need to properly compute this brush
8437 for (w = 0;w < numplanes;w++)
8438 maxdist = max(maxdist, fabs(planes[w].dist));
8439 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8440 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8441 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8445 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8446 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8448 if (planenum2 == planenum)
8450 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);
8453 if (tempnumpoints < 3)
8455 // generate elements forming a triangle fan for this polygon
8456 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8460 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)
8462 texturelayer_t *layer;
8463 layer = t->currentlayers + t->currentnumlayers++;
8465 layer->depthmask = depthmask;
8466 layer->blendfunc1 = blendfunc1;
8467 layer->blendfunc2 = blendfunc2;
8468 layer->texture = texture;
8469 layer->texmatrix = *matrix;
8470 layer->color[0] = r;
8471 layer->color[1] = g;
8472 layer->color[2] = b;
8473 layer->color[3] = a;
8476 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8479 index = parms[2] + r_refdef.scene.time * parms[3];
8480 index -= floor(index);
8484 case Q3WAVEFUNC_NONE:
8485 case Q3WAVEFUNC_NOISE:
8486 case Q3WAVEFUNC_COUNT:
8489 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8490 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8491 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8492 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8493 case Q3WAVEFUNC_TRIANGLE:
8495 f = index - floor(index);
8506 return (float)(parms[0] + parms[1] * f);
8509 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8514 matrix4x4_t matrix, temp;
8515 switch(tcmod->tcmod)
8519 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8520 matrix = r_waterscrollmatrix;
8522 matrix = identitymatrix;
8524 case Q3TCMOD_ENTITYTRANSLATE:
8525 // this is used in Q3 to allow the gamecode to control texcoord
8526 // scrolling on the entity, which is not supported in darkplaces yet.
8527 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8529 case Q3TCMOD_ROTATE:
8530 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8531 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8532 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8535 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8537 case Q3TCMOD_SCROLL:
8538 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8540 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8541 w = (int) tcmod->parms[0];
8542 h = (int) tcmod->parms[1];
8543 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8545 idx = (int) floor(f * w * h);
8546 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8548 case Q3TCMOD_STRETCH:
8549 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8550 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8552 case Q3TCMOD_TRANSFORM:
8553 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8554 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8555 VectorSet(tcmat + 6, 0 , 0 , 1);
8556 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8557 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8559 case Q3TCMOD_TURBULENT:
8560 // this is handled in the RSurf_PrepareVertices function
8561 matrix = identitymatrix;
8565 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8568 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8570 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8571 char name[MAX_QPATH];
8572 skinframe_t *skinframe;
8573 unsigned char pixels[296*194];
8574 strlcpy(cache->name, skinname, sizeof(cache->name));
8575 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8576 if (developer_loading.integer)
8577 Con_Printf("loading %s\n", name);
8578 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8579 if (!skinframe || !skinframe->base)
8582 fs_offset_t filesize;
8584 f = FS_LoadFile(name, tempmempool, true, &filesize);
8587 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8588 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8592 cache->skinframe = skinframe;
8595 texture_t *R_GetCurrentTexture(texture_t *t)
8598 const entity_render_t *ent = rsurface.entity;
8599 dp_model_t *model = ent->model;
8600 q3shaderinfo_layer_tcmod_t *tcmod;
8602 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8603 return t->currentframe;
8604 t->update_lastrenderframe = r_textureframe;
8605 t->update_lastrenderentity = (void *)ent;
8607 // switch to an alternate material if this is a q1bsp animated material
8609 texture_t *texture = t;
8610 int s = rsurface.ent_skinnum;
8611 if ((unsigned int)s >= (unsigned int)model->numskins)
8613 if (model->skinscenes)
8615 if (model->skinscenes[s].framecount > 1)
8616 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8618 s = model->skinscenes[s].firstframe;
8621 t = t + s * model->num_surfaces;
8624 // use an alternate animation if the entity's frame is not 0,
8625 // and only if the texture has an alternate animation
8626 if (rsurface.ent_alttextures && t->anim_total[1])
8627 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8629 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8631 texture->currentframe = t;
8634 // update currentskinframe to be a qw skin or animation frame
8635 if (rsurface.ent_qwskin >= 0)
8637 i = rsurface.ent_qwskin;
8638 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8640 r_qwskincache_size = cl.maxclients;
8642 Mem_Free(r_qwskincache);
8643 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8645 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8646 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8647 t->currentskinframe = r_qwskincache[i].skinframe;
8648 if (t->currentskinframe == NULL)
8649 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8651 else if (t->numskinframes >= 2)
8652 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8653 if (t->backgroundnumskinframes >= 2)
8654 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8656 t->currentmaterialflags = t->basematerialflags;
8657 t->currentalpha = rsurface.colormod[3];
8658 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8659 t->currentalpha *= r_wateralpha.value;
8660 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8661 t->currentalpha *= t->r_water_wateralpha;
8662 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8663 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8664 if (!(rsurface.ent_flags & RENDER_LIGHT))
8665 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8666 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8668 // pick a model lighting mode
8669 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8670 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8672 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8674 if (rsurface.ent_flags & RENDER_ADDITIVE)
8675 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8676 else if (t->currentalpha < 1)
8677 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8678 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8679 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8680 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8681 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8682 if (t->backgroundnumskinframes)
8683 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8684 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8686 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8687 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8690 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8691 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8692 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8694 // there is no tcmod
8695 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8697 t->currenttexmatrix = r_waterscrollmatrix;
8698 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8700 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8702 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8703 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8706 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8707 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8708 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8709 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8711 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8712 if (t->currentskinframe->qpixels)
8713 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8714 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8715 if (!t->basetexture)
8716 t->basetexture = r_texture_notexture;
8717 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8718 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8719 t->nmaptexture = t->currentskinframe->nmap;
8720 if (!t->nmaptexture)
8721 t->nmaptexture = r_texture_blanknormalmap;
8722 t->glosstexture = r_texture_black;
8723 t->glowtexture = t->currentskinframe->glow;
8724 t->fogtexture = t->currentskinframe->fog;
8725 if (t->backgroundnumskinframes)
8727 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8728 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8729 t->backgroundglosstexture = r_texture_black;
8730 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8731 if (!t->backgroundnmaptexture)
8732 t->backgroundnmaptexture = r_texture_blanknormalmap;
8736 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8737 t->backgroundnmaptexture = r_texture_blanknormalmap;
8738 t->backgroundglosstexture = r_texture_black;
8739 t->backgroundglowtexture = NULL;
8741 t->specularpower = r_shadow_glossexponent.value;
8742 // TODO: store reference values for these in the texture?
8743 t->specularscale = 0;
8744 if (r_shadow_gloss.integer > 0)
8746 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8748 if (r_shadow_glossintensity.value > 0)
8750 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8751 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8752 t->specularscale = r_shadow_glossintensity.value;
8755 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8757 t->glosstexture = r_texture_white;
8758 t->backgroundglosstexture = r_texture_white;
8759 t->specularscale = r_shadow_gloss2intensity.value;
8760 t->specularpower = r_shadow_gloss2exponent.value;
8763 t->specularscale *= t->specularscalemod;
8764 t->specularpower *= t->specularpowermod;
8766 // lightmaps mode looks bad with dlights using actual texturing, so turn
8767 // off the colormap and glossmap, but leave the normalmap on as it still
8768 // accurately represents the shading involved
8769 if (gl_lightmaps.integer)
8771 t->basetexture = r_texture_grey128;
8772 t->pantstexture = r_texture_black;
8773 t->shirttexture = r_texture_black;
8774 t->nmaptexture = r_texture_blanknormalmap;
8775 t->glosstexture = r_texture_black;
8776 t->glowtexture = NULL;
8777 t->fogtexture = NULL;
8778 t->backgroundbasetexture = NULL;
8779 t->backgroundnmaptexture = r_texture_blanknormalmap;
8780 t->backgroundglosstexture = r_texture_black;
8781 t->backgroundglowtexture = NULL;
8782 t->specularscale = 0;
8783 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8786 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8787 VectorClear(t->dlightcolor);
8788 t->currentnumlayers = 0;
8789 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8791 int blendfunc1, blendfunc2;
8793 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8795 blendfunc1 = GL_SRC_ALPHA;
8796 blendfunc2 = GL_ONE;
8798 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8800 blendfunc1 = GL_SRC_ALPHA;
8801 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8803 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8805 blendfunc1 = t->customblendfunc[0];
8806 blendfunc2 = t->customblendfunc[1];
8810 blendfunc1 = GL_ONE;
8811 blendfunc2 = GL_ZERO;
8813 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8814 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8816 // fullbright is not affected by r_refdef.lightmapintensity
8817 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]);
8818 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8819 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]);
8820 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8821 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]);
8825 vec3_t ambientcolor;
8827 // set the color tint used for lights affecting this surface
8828 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8830 // q3bsp has no lightmap updates, so the lightstylevalue that
8831 // would normally be baked into the lightmap must be
8832 // applied to the color
8833 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8834 if (model->type == mod_brushq3)
8835 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8836 colorscale *= r_refdef.lightmapintensity;
8837 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8838 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8839 // basic lit geometry
8840 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]);
8841 // add pants/shirt if needed
8842 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8843 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]);
8844 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8845 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]);
8846 // now add ambient passes if needed
8847 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8849 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]);
8850 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8851 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]);
8852 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8853 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]);
8856 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8857 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]);
8858 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8860 // if this is opaque use alpha blend which will darken the earlier
8863 // if this is an alpha blended material, all the earlier passes
8864 // were darkened by fog already, so we only need to add the fog
8865 // color ontop through the fog mask texture
8867 // if this is an additive blended material, all the earlier passes
8868 // were darkened by fog already, and we should not add fog color
8869 // (because the background was not darkened, there is no fog color
8870 // that was lost behind it).
8871 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]);
8875 return t->currentframe;
8878 rsurfacestate_t rsurface;
8880 void R_Mesh_ResizeArrays(int newvertices)
8883 if (rsurface.array_size >= newvertices)
8885 if (rsurface.array_modelvertex3f)
8886 Mem_Free(rsurface.array_modelvertex3f);
8887 rsurface.array_size = (newvertices + 1023) & ~1023;
8888 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8889 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
8890 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
8891 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
8892 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
8893 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
8894 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8895 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8896 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
8897 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
8898 rsurface.array_color4f = base + rsurface.array_size * 27;
8899 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8902 void RSurf_ActiveWorldEntity(void)
8904 dp_model_t *model = r_refdef.scene.worldmodel;
8905 //if (rsurface.entity == r_refdef.scene.worldentity)
8907 rsurface.entity = r_refdef.scene.worldentity;
8908 rsurface.skeleton = NULL;
8909 rsurface.ent_skinnum = 0;
8910 rsurface.ent_qwskin = -1;
8911 rsurface.ent_shadertime = 0;
8912 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8913 if (rsurface.array_size < model->surfmesh.num_vertices)
8914 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8915 rsurface.matrix = identitymatrix;
8916 rsurface.inversematrix = identitymatrix;
8917 rsurface.matrixscale = 1;
8918 rsurface.inversematrixscale = 1;
8919 R_EntityMatrix(&identitymatrix);
8920 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8921 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8922 rsurface.fograngerecip = r_refdef.fograngerecip;
8923 rsurface.fogheightfade = r_refdef.fogheightfade;
8924 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8925 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8926 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8927 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8928 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8929 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8930 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8931 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8932 rsurface.colormod[3] = 1;
8933 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);
8934 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8935 rsurface.frameblend[0].lerp = 1;
8936 rsurface.ent_alttextures = false;
8937 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8938 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8939 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8940 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8941 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8942 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8943 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8944 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8945 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8946 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8947 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8948 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8949 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8950 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8951 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8952 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8953 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8954 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8955 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8956 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8957 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8958 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8959 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8960 rsurface.modelelement3i = model->surfmesh.data_element3i;
8961 rsurface.modelelement3s = model->surfmesh.data_element3s;
8962 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8963 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8964 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8965 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8966 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8967 rsurface.modelsurfaces = model->data_surfaces;
8968 rsurface.generatedvertex = false;
8969 rsurface.vertex3f = rsurface.modelvertex3f;
8970 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8971 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8972 rsurface.svector3f = rsurface.modelsvector3f;
8973 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8974 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8975 rsurface.tvector3f = rsurface.modeltvector3f;
8976 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8977 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8978 rsurface.normal3f = rsurface.modelnormal3f;
8979 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8980 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8981 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8984 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8986 dp_model_t *model = ent->model;
8987 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8989 rsurface.entity = (entity_render_t *)ent;
8990 rsurface.skeleton = ent->skeleton;
8991 rsurface.ent_skinnum = ent->skinnum;
8992 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;
8993 rsurface.ent_shadertime = ent->shadertime;
8994 rsurface.ent_flags = ent->flags;
8995 if (rsurface.array_size < model->surfmesh.num_vertices)
8996 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8997 rsurface.matrix = ent->matrix;
8998 rsurface.inversematrix = ent->inversematrix;
8999 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9000 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9001 R_EntityMatrix(&rsurface.matrix);
9002 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9003 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9004 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9005 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9006 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9007 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9008 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9009 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9010 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9011 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9012 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9013 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9014 rsurface.colormod[3] = ent->alpha;
9015 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9016 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9017 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9018 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9019 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9020 if (ent->model->brush.submodel && !prepass)
9022 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9023 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9025 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9027 if (ent->animcache_vertex3f && !r_framedata_failed)
9029 rsurface.modelvertex3f = ent->animcache_vertex3f;
9030 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9031 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9032 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9034 else if (wanttangents)
9036 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9037 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9038 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9039 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9040 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9042 else if (wantnormals)
9044 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9045 rsurface.modelsvector3f = NULL;
9046 rsurface.modeltvector3f = NULL;
9047 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9048 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9052 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9053 rsurface.modelsvector3f = NULL;
9054 rsurface.modeltvector3f = NULL;
9055 rsurface.modelnormal3f = NULL;
9056 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9058 rsurface.modelvertex3f_bufferobject = 0;
9059 rsurface.modelvertex3f_bufferoffset = 0;
9060 rsurface.modelsvector3f_bufferobject = 0;
9061 rsurface.modelsvector3f_bufferoffset = 0;
9062 rsurface.modeltvector3f_bufferobject = 0;
9063 rsurface.modeltvector3f_bufferoffset = 0;
9064 rsurface.modelnormal3f_bufferobject = 0;
9065 rsurface.modelnormal3f_bufferoffset = 0;
9066 rsurface.generatedvertex = true;
9070 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9071 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9072 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9073 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9074 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9075 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9076 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9077 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9078 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9079 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9080 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9081 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9082 rsurface.generatedvertex = false;
9084 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9085 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9086 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9087 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9088 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9089 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9090 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9091 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9092 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9093 rsurface.modelelement3i = model->surfmesh.data_element3i;
9094 rsurface.modelelement3s = model->surfmesh.data_element3s;
9095 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9096 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9097 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9098 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9099 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9100 rsurface.modelsurfaces = model->data_surfaces;
9101 rsurface.vertex3f = rsurface.modelvertex3f;
9102 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9103 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9104 rsurface.svector3f = rsurface.modelsvector3f;
9105 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9106 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9107 rsurface.tvector3f = rsurface.modeltvector3f;
9108 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9109 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9110 rsurface.normal3f = rsurface.modelnormal3f;
9111 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9112 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9113 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9116 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)
9118 rsurface.entity = r_refdef.scene.worldentity;
9119 rsurface.skeleton = NULL;
9120 rsurface.ent_skinnum = 0;
9121 rsurface.ent_qwskin = -1;
9122 rsurface.ent_shadertime = shadertime;
9123 rsurface.ent_flags = entflags;
9124 rsurface.modelnum_vertices = numvertices;
9125 rsurface.modelnum_triangles = numtriangles;
9126 if (rsurface.array_size < rsurface.modelnum_vertices)
9127 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9128 rsurface.matrix = *matrix;
9129 rsurface.inversematrix = *inversematrix;
9130 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9131 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9132 R_EntityMatrix(&rsurface.matrix);
9133 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9134 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9135 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9136 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9137 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9138 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9139 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9140 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9141 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9142 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9143 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9144 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9145 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);
9146 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9147 rsurface.frameblend[0].lerp = 1;
9148 rsurface.ent_alttextures = false;
9149 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9150 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9153 rsurface.modelvertex3f = vertex3f;
9154 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9155 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9156 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9158 else if (wantnormals)
9160 rsurface.modelvertex3f = vertex3f;
9161 rsurface.modelsvector3f = NULL;
9162 rsurface.modeltvector3f = NULL;
9163 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9167 rsurface.modelvertex3f = vertex3f;
9168 rsurface.modelsvector3f = NULL;
9169 rsurface.modeltvector3f = NULL;
9170 rsurface.modelnormal3f = NULL;
9172 rsurface.modelvertex3f_bufferobject = 0;
9173 rsurface.modelvertex3f_bufferoffset = 0;
9174 rsurface.modelsvector3f_bufferobject = 0;
9175 rsurface.modelsvector3f_bufferoffset = 0;
9176 rsurface.modeltvector3f_bufferobject = 0;
9177 rsurface.modeltvector3f_bufferoffset = 0;
9178 rsurface.modelnormal3f_bufferobject = 0;
9179 rsurface.modelnormal3f_bufferoffset = 0;
9180 rsurface.generatedvertex = true;
9181 rsurface.modellightmapcolor4f = color4f;
9182 rsurface.modellightmapcolor4f_bufferobject = 0;
9183 rsurface.modellightmapcolor4f_bufferoffset = 0;
9184 rsurface.modeltexcoordtexture2f = texcoord2f;
9185 rsurface.modeltexcoordtexture2f_bufferobject = 0;
9186 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9187 rsurface.modeltexcoordlightmap2f = NULL;
9188 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9189 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9190 rsurface.modelelement3i = element3i;
9191 rsurface.modelelement3s = element3s;
9192 rsurface.modelelement3i_bufferobject = 0;
9193 rsurface.modelelement3s_bufferobject = 0;
9194 rsurface.modellightmapoffsets = NULL;
9195 rsurface.modelsurfaces = NULL;
9196 rsurface.vertex3f = rsurface.modelvertex3f;
9197 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9198 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9199 rsurface.svector3f = rsurface.modelsvector3f;
9200 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9201 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9202 rsurface.tvector3f = rsurface.modeltvector3f;
9203 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9204 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9205 rsurface.normal3f = rsurface.modelnormal3f;
9206 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9207 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9208 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9210 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9212 if ((wantnormals || wanttangents) && !normal3f)
9213 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9214 if (wanttangents && !svector3f)
9215 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);
9219 float RSurf_FogPoint(const float *v)
9221 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9222 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9223 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9224 float FogHeightFade = r_refdef.fogheightfade;
9226 unsigned int fogmasktableindex;
9227 if (r_refdef.fogplaneviewabove)
9228 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9230 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9231 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9232 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9235 float RSurf_FogVertex(const float *v)
9237 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9238 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9239 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9240 float FogHeightFade = rsurface.fogheightfade;
9242 unsigned int fogmasktableindex;
9243 if (r_refdef.fogplaneviewabove)
9244 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9246 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9247 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9248 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9251 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9252 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9255 int texturesurfaceindex;
9260 const float *v1, *in_tc;
9262 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9264 q3shaderinfo_deform_t *deform;
9265 // 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
9266 if (rsurface.generatedvertex)
9268 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9269 generatenormals = true;
9270 for (i = 0;i < Q3MAXDEFORMS;i++)
9272 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9274 generatetangents = true;
9275 generatenormals = true;
9277 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9278 generatenormals = true;
9280 if (generatenormals && !rsurface.modelnormal3f)
9282 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9283 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9284 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9285 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9287 if (generatetangents && !rsurface.modelsvector3f)
9289 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9290 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9291 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9292 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9293 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9294 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9295 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);
9298 rsurface.vertex3f = rsurface.modelvertex3f;
9299 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9300 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9301 rsurface.svector3f = rsurface.modelsvector3f;
9302 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9303 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9304 rsurface.tvector3f = rsurface.modeltvector3f;
9305 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9306 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9307 rsurface.normal3f = rsurface.modelnormal3f;
9308 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9309 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9310 // if vertices are deformed (sprite flares and things in maps, possibly
9311 // water waves, bulges and other deformations), generate them into
9312 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9313 // (may be static model data or generated data for an animated model, or
9314 // the previous deform pass)
9315 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9317 switch (deform->deform)
9320 case Q3DEFORM_PROJECTIONSHADOW:
9321 case Q3DEFORM_TEXT0:
9322 case Q3DEFORM_TEXT1:
9323 case Q3DEFORM_TEXT2:
9324 case Q3DEFORM_TEXT3:
9325 case Q3DEFORM_TEXT4:
9326 case Q3DEFORM_TEXT5:
9327 case Q3DEFORM_TEXT6:
9328 case Q3DEFORM_TEXT7:
9331 case Q3DEFORM_AUTOSPRITE:
9332 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9333 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9334 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9335 VectorNormalize(newforward);
9336 VectorNormalize(newright);
9337 VectorNormalize(newup);
9338 // make deformed versions of only the model vertices used by the specified surfaces
9339 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9341 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9342 // a single autosprite surface can contain multiple sprites...
9343 for (j = 0;j < surface->num_vertices - 3;j += 4)
9345 VectorClear(center);
9346 for (i = 0;i < 4;i++)
9347 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9348 VectorScale(center, 0.25f, center);
9349 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9350 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9351 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9352 for (i = 0;i < 4;i++)
9354 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9355 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9358 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);
9359 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);
9361 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9362 rsurface.vertex3f_bufferobject = 0;
9363 rsurface.vertex3f_bufferoffset = 0;
9364 rsurface.svector3f = rsurface.array_deformedsvector3f;
9365 rsurface.svector3f_bufferobject = 0;
9366 rsurface.svector3f_bufferoffset = 0;
9367 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9368 rsurface.tvector3f_bufferobject = 0;
9369 rsurface.tvector3f_bufferoffset = 0;
9370 rsurface.normal3f = rsurface.array_deformednormal3f;
9371 rsurface.normal3f_bufferobject = 0;
9372 rsurface.normal3f_bufferoffset = 0;
9374 case Q3DEFORM_AUTOSPRITE2:
9375 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9376 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9377 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9378 VectorNormalize(newforward);
9379 VectorNormalize(newright);
9380 VectorNormalize(newup);
9381 // make deformed versions of only the model vertices used by the specified surfaces
9382 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9384 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9385 const float *v1, *v2;
9395 memset(shortest, 0, sizeof(shortest));
9396 // a single autosprite surface can contain multiple sprites...
9397 for (j = 0;j < surface->num_vertices - 3;j += 4)
9399 VectorClear(center);
9400 for (i = 0;i < 4;i++)
9401 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9402 VectorScale(center, 0.25f, center);
9403 // find the two shortest edges, then use them to define the
9404 // axis vectors for rotating around the central axis
9405 for (i = 0;i < 6;i++)
9407 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9408 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9410 Debug_PolygonBegin(NULL, 0);
9411 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9412 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);
9413 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9416 l = VectorDistance2(v1, v2);
9417 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9419 l += (1.0f / 1024.0f);
9420 if (shortest[0].length2 > l || i == 0)
9422 shortest[1] = shortest[0];
9423 shortest[0].length2 = l;
9424 shortest[0].v1 = v1;
9425 shortest[0].v2 = v2;
9427 else if (shortest[1].length2 > l || i == 1)
9429 shortest[1].length2 = l;
9430 shortest[1].v1 = v1;
9431 shortest[1].v2 = v2;
9434 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9435 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9437 Debug_PolygonBegin(NULL, 0);
9438 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9439 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);
9440 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9443 // this calculates the right vector from the shortest edge
9444 // and the up vector from the edge midpoints
9445 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9446 VectorNormalize(right);
9447 VectorSubtract(end, start, up);
9448 VectorNormalize(up);
9449 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9450 VectorSubtract(rsurface.localvieworigin, center, forward);
9451 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9452 VectorNegate(forward, forward);
9453 VectorReflect(forward, 0, up, forward);
9454 VectorNormalize(forward);
9455 CrossProduct(up, forward, newright);
9456 VectorNormalize(newright);
9458 Debug_PolygonBegin(NULL, 0);
9459 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);
9460 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9461 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9465 Debug_PolygonBegin(NULL, 0);
9466 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9467 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9468 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9471 // rotate the quad around the up axis vector, this is made
9472 // especially easy by the fact we know the quad is flat,
9473 // so we only have to subtract the center position and
9474 // measure distance along the right vector, and then
9475 // multiply that by the newright vector and add back the
9477 // we also need to subtract the old position to undo the
9478 // displacement from the center, which we do with a
9479 // DotProduct, the subtraction/addition of center is also
9480 // optimized into DotProducts here
9481 l = DotProduct(right, center);
9482 for (i = 0;i < 4;i++)
9484 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9485 f = DotProduct(right, v1) - l;
9486 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9489 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);
9490 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);
9492 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9493 rsurface.vertex3f_bufferobject = 0;
9494 rsurface.vertex3f_bufferoffset = 0;
9495 rsurface.svector3f = rsurface.array_deformedsvector3f;
9496 rsurface.svector3f_bufferobject = 0;
9497 rsurface.svector3f_bufferoffset = 0;
9498 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9499 rsurface.tvector3f_bufferobject = 0;
9500 rsurface.tvector3f_bufferoffset = 0;
9501 rsurface.normal3f = rsurface.array_deformednormal3f;
9502 rsurface.normal3f_bufferobject = 0;
9503 rsurface.normal3f_bufferoffset = 0;
9505 case Q3DEFORM_NORMAL:
9506 // deform the normals to make reflections wavey
9507 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9509 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9510 for (j = 0;j < surface->num_vertices;j++)
9513 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9514 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9515 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9516 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9517 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9518 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9519 VectorNormalize(normal);
9521 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);
9523 rsurface.svector3f = rsurface.array_deformedsvector3f;
9524 rsurface.svector3f_bufferobject = 0;
9525 rsurface.svector3f_bufferoffset = 0;
9526 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9527 rsurface.tvector3f_bufferobject = 0;
9528 rsurface.tvector3f_bufferoffset = 0;
9529 rsurface.normal3f = rsurface.array_deformednormal3f;
9530 rsurface.normal3f_bufferobject = 0;
9531 rsurface.normal3f_bufferoffset = 0;
9534 // deform vertex array to make wavey water and flags and such
9535 waveparms[0] = deform->waveparms[0];
9536 waveparms[1] = deform->waveparms[1];
9537 waveparms[2] = deform->waveparms[2];
9538 waveparms[3] = deform->waveparms[3];
9539 // this is how a divisor of vertex influence on deformation
9540 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9541 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9542 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9544 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9545 for (j = 0;j < surface->num_vertices;j++)
9547 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
9548 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
9549 // if the wavefunc depends on time, evaluate it per-vertex
9552 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9553 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9555 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
9558 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9559 rsurface.vertex3f_bufferobject = 0;
9560 rsurface.vertex3f_bufferoffset = 0;
9562 case Q3DEFORM_BULGE:
9563 // deform vertex array to make the surface have moving bulges
9564 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9566 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9567 for (j = 0;j < surface->num_vertices;j++)
9569 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9570 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9573 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9574 rsurface.vertex3f_bufferobject = 0;
9575 rsurface.vertex3f_bufferoffset = 0;
9578 // deform vertex array
9579 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9580 VectorScale(deform->parms, scale, waveparms);
9581 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9583 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9584 for (j = 0;j < surface->num_vertices;j++)
9585 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9587 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9588 rsurface.vertex3f_bufferobject = 0;
9589 rsurface.vertex3f_bufferoffset = 0;
9593 // generate texcoords based on the chosen texcoord source
9594 switch(rsurface.texture->tcgen.tcgen)
9597 case Q3TCGEN_TEXTURE:
9598 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9599 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
9600 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9602 case Q3TCGEN_LIGHTMAP:
9603 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
9604 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9605 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9607 case Q3TCGEN_VECTOR:
9608 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9610 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9611 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)
9613 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9614 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9617 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9618 rsurface.texcoordtexture2f_bufferobject = 0;
9619 rsurface.texcoordtexture2f_bufferoffset = 0;
9621 case Q3TCGEN_ENVIRONMENT:
9622 // make environment reflections using a spheremap
9623 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9625 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9626 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9627 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9628 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9629 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9631 // identical to Q3A's method, but executed in worldspace so
9632 // carried models can be shiny too
9634 float viewer[3], d, reflected[3], worldreflected[3];
9636 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9637 // VectorNormalize(viewer);
9639 d = DotProduct(normal, viewer);
9641 reflected[0] = normal[0]*2*d - viewer[0];
9642 reflected[1] = normal[1]*2*d - viewer[1];
9643 reflected[2] = normal[2]*2*d - viewer[2];
9644 // note: this is proportinal to viewer, so we can normalize later
9646 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9647 VectorNormalize(worldreflected);
9649 // note: this sphere map only uses world x and z!
9650 // so positive and negative y will LOOK THE SAME.
9651 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9652 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9655 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9656 rsurface.texcoordtexture2f_bufferobject = 0;
9657 rsurface.texcoordtexture2f_bufferoffset = 0;
9660 // the only tcmod that needs software vertex processing is turbulent, so
9661 // check for it here and apply the changes if needed
9662 // and we only support that as the first one
9663 // (handling a mixture of turbulent and other tcmods would be problematic
9664 // without punting it entirely to a software path)
9665 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9667 amplitude = rsurface.texture->tcmods[0].parms[1];
9668 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9669 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9671 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9672 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)
9674 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9675 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9678 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9679 rsurface.texcoordtexture2f_bufferobject = 0;
9680 rsurface.texcoordtexture2f_bufferoffset = 0;
9682 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9683 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9684 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9685 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9688 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9691 const msurface_t *surface = texturesurfacelist[0];
9692 const msurface_t *surface2;
9697 // TODO: lock all array ranges before render, rather than on each surface
9698 if (texturenumsurfaces == 1)
9699 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);
9700 else if (r_batchmode.integer == 2)
9702 #define MAXBATCHTRIANGLES 4096
9703 int batchtriangles = 0;
9704 static int batchelements[MAXBATCHTRIANGLES*3];
9705 for (i = 0;i < texturenumsurfaces;i = j)
9707 surface = texturesurfacelist[i];
9709 if (surface->num_triangles > MAXBATCHTRIANGLES)
9711 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);
9714 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9715 batchtriangles = surface->num_triangles;
9716 firstvertex = surface->num_firstvertex;
9717 endvertex = surface->num_firstvertex + surface->num_vertices;
9718 for (;j < texturenumsurfaces;j++)
9720 surface2 = texturesurfacelist[j];
9721 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9723 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9724 batchtriangles += surface2->num_triangles;
9725 firstvertex = min(firstvertex, surface2->num_firstvertex);
9726 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9728 surface2 = texturesurfacelist[j-1];
9729 numvertices = endvertex - firstvertex;
9730 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9733 else if (r_batchmode.integer == 1)
9735 for (i = 0;i < texturenumsurfaces;i = j)
9737 surface = texturesurfacelist[i];
9738 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9739 if (texturesurfacelist[j] != surface2)
9741 surface2 = texturesurfacelist[j-1];
9742 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9743 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9744 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9749 for (i = 0;i < texturenumsurfaces;i++)
9751 surface = texturesurfacelist[i];
9752 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);
9757 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9759 switch(vid.renderpath)
9761 case RENDERPATH_CGGL:
9763 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9764 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9767 case RENDERPATH_GL20:
9768 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9769 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9771 case RENDERPATH_GL13:
9772 case RENDERPATH_GL11:
9773 R_Mesh_TexBind(0, surface->lightmaptexture);
9778 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9780 // pick the closest matching water plane and bind textures
9781 int planeindex, vertexindex;
9785 r_waterstate_waterplane_t *p, *bestp;
9788 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9791 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9793 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9794 d += fabs(PlaneDiff(vert, &p->plane));
9796 if (bestd > d || !bestp)
9802 switch(vid.renderpath)
9804 case RENDERPATH_CGGL:
9806 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9807 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9810 case RENDERPATH_GL20:
9811 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9812 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9814 case RENDERPATH_GL13:
9815 case RENDERPATH_GL11:
9820 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9823 const msurface_t *surface;
9824 if (r_waterstate.renderingscene)
9826 for (i = 0;i < texturenumsurfaces;i++)
9828 surface = texturesurfacelist[i];
9829 RSurf_BindLightmapForSurface(surface);
9830 RSurf_BindReflectionForSurface(surface);
9831 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);
9835 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9839 const msurface_t *surface = texturesurfacelist[0];
9840 const msurface_t *surface2;
9845 if (texturenumsurfaces == 1)
9847 RSurf_BindLightmapForSurface(surface);
9848 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);
9850 else if (r_batchmode.integer == 2)
9852 #define MAXBATCHTRIANGLES 4096
9853 int batchtriangles = 0;
9854 static int batchelements[MAXBATCHTRIANGLES*3];
9855 for (i = 0;i < texturenumsurfaces;i = j)
9857 surface = texturesurfacelist[i];
9858 RSurf_BindLightmapForSurface(surface);
9860 if (surface->num_triangles > MAXBATCHTRIANGLES)
9862 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);
9865 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9866 batchtriangles = surface->num_triangles;
9867 firstvertex = surface->num_firstvertex;
9868 endvertex = surface->num_firstvertex + surface->num_vertices;
9869 for (;j < texturenumsurfaces;j++)
9871 surface2 = texturesurfacelist[j];
9872 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9874 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9875 batchtriangles += surface2->num_triangles;
9876 firstvertex = min(firstvertex, surface2->num_firstvertex);
9877 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9879 surface2 = texturesurfacelist[j-1];
9880 numvertices = endvertex - firstvertex;
9881 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9884 else if (r_batchmode.integer == 1)
9887 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9888 for (i = 0;i < texturenumsurfaces;i = j)
9890 surface = texturesurfacelist[i];
9891 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9892 if (texturesurfacelist[j] != surface2)
9894 Con_Printf(" %i", j - i);
9897 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9899 for (i = 0;i < texturenumsurfaces;i = j)
9901 surface = texturesurfacelist[i];
9902 RSurf_BindLightmapForSurface(surface);
9903 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9904 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9907 Con_Printf(" %i", j - i);
9909 surface2 = texturesurfacelist[j-1];
9910 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9911 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9912 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9920 for (i = 0;i < texturenumsurfaces;i++)
9922 surface = texturesurfacelist[i];
9923 RSurf_BindLightmapForSurface(surface);
9924 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);
9929 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9932 int texturesurfaceindex;
9933 if (r_showsurfaces.integer == 2)
9935 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9937 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9938 for (j = 0;j < surface->num_triangles;j++)
9940 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9941 GL_Color(f, f, f, 1);
9942 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9948 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9950 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9951 int k = (int)(((size_t)surface) / sizeof(msurface_t));
9952 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);
9953 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);
9958 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9960 int texturesurfaceindex;
9964 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9966 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9967 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)
9975 rsurface.lightmapcolor4f = rsurface.array_color4f;
9976 rsurface.lightmapcolor4f_bufferobject = 0;
9977 rsurface.lightmapcolor4f_bufferoffset = 0;
9980 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9982 int texturesurfaceindex;
9988 if (rsurface.lightmapcolor4f)
9990 // generate color arrays for the surfaces in this list
9991 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9993 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9994 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)
9996 f = RSurf_FogVertex(v);
10006 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10008 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10009 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)
10011 f = RSurf_FogVertex(v);
10019 rsurface.lightmapcolor4f = rsurface.array_color4f;
10020 rsurface.lightmapcolor4f_bufferobject = 0;
10021 rsurface.lightmapcolor4f_bufferoffset = 0;
10024 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10026 int texturesurfaceindex;
10032 if (!rsurface.lightmapcolor4f)
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 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)
10040 f = RSurf_FogVertex(v);
10041 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10042 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10043 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10047 rsurface.lightmapcolor4f = rsurface.array_color4f;
10048 rsurface.lightmapcolor4f_bufferobject = 0;
10049 rsurface.lightmapcolor4f_bufferoffset = 0;
10052 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10054 int texturesurfaceindex;
10058 if (!rsurface.lightmapcolor4f)
10060 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10062 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10063 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)
10071 rsurface.lightmapcolor4f = rsurface.array_color4f;
10072 rsurface.lightmapcolor4f_bufferobject = 0;
10073 rsurface.lightmapcolor4f_bufferoffset = 0;
10076 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10078 int texturesurfaceindex;
10082 if (!rsurface.lightmapcolor4f)
10084 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10086 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10087 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)
10089 c2[0] = c[0] + r_refdef.scene.ambient;
10090 c2[1] = c[1] + r_refdef.scene.ambient;
10091 c2[2] = c[2] + r_refdef.scene.ambient;
10095 rsurface.lightmapcolor4f = rsurface.array_color4f;
10096 rsurface.lightmapcolor4f_bufferobject = 0;
10097 rsurface.lightmapcolor4f_bufferoffset = 0;
10100 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10103 rsurface.lightmapcolor4f = NULL;
10104 rsurface.lightmapcolor4f_bufferobject = 0;
10105 rsurface.lightmapcolor4f_bufferoffset = 0;
10106 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10107 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10108 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10109 GL_Color(r, g, b, a);
10110 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10113 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10115 // TODO: optimize applyfog && applycolor case
10116 // just apply fog if necessary, and tint the fog color array if necessary
10117 rsurface.lightmapcolor4f = NULL;
10118 rsurface.lightmapcolor4f_bufferobject = 0;
10119 rsurface.lightmapcolor4f_bufferoffset = 0;
10120 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10121 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10122 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10123 GL_Color(r, g, b, a);
10124 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10127 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10129 int texturesurfaceindex;
10133 if (texturesurfacelist[0]->lightmapinfo)
10135 // generate color arrays for the surfaces in this list
10136 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10138 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10139 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10141 if (surface->lightmapinfo->samples)
10143 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10144 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10145 VectorScale(lm, scale, c);
10146 if (surface->lightmapinfo->styles[1] != 255)
10148 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10150 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10151 VectorMA(c, scale, lm, c);
10152 if (surface->lightmapinfo->styles[2] != 255)
10155 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10156 VectorMA(c, scale, lm, c);
10157 if (surface->lightmapinfo->styles[3] != 255)
10160 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10161 VectorMA(c, scale, lm, c);
10171 rsurface.lightmapcolor4f = rsurface.array_color4f;
10172 rsurface.lightmapcolor4f_bufferobject = 0;
10173 rsurface.lightmapcolor4f_bufferoffset = 0;
10177 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10178 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10179 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10181 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10182 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10183 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10184 GL_Color(r, g, b, a);
10185 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10188 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10190 int texturesurfaceindex;
10197 vec3_t ambientcolor;
10198 vec3_t diffusecolor;
10202 VectorCopy(rsurface.modellight_lightdir, lightdir);
10203 f = 0.5f * r_refdef.lightmapintensity;
10204 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10205 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10206 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10207 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10208 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10209 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10211 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10213 // generate color arrays for the surfaces in this list
10214 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10216 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10217 int numverts = surface->num_vertices;
10218 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10219 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10220 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10221 // q3-style directional shading
10222 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10224 if ((f = DotProduct(n, lightdir)) > 0)
10225 VectorMA(ambientcolor, f, diffusecolor, c);
10227 VectorCopy(ambientcolor, c);
10235 rsurface.lightmapcolor4f = rsurface.array_color4f;
10236 rsurface.lightmapcolor4f_bufferobject = 0;
10237 rsurface.lightmapcolor4f_bufferoffset = 0;
10238 *applycolor = false;
10242 *r = ambientcolor[0];
10243 *g = ambientcolor[1];
10244 *b = ambientcolor[2];
10245 rsurface.lightmapcolor4f = NULL;
10246 rsurface.lightmapcolor4f_bufferobject = 0;
10247 rsurface.lightmapcolor4f_bufferoffset = 0;
10251 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10253 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10254 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10255 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10256 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10257 GL_Color(r, g, b, a);
10258 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10261 void RSurf_SetupDepthAndCulling(void)
10263 // submodels are biased to avoid z-fighting with world surfaces that they
10264 // may be exactly overlapping (avoids z-fighting artifacts on certain
10265 // doors and things in Quake maps)
10266 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10267 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10268 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10269 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10272 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10274 // transparent sky would be ridiculous
10275 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10277 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10278 skyrenderlater = true;
10279 RSurf_SetupDepthAndCulling();
10280 GL_DepthMask(true);
10281 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10282 // skymasking on them, and Quake3 never did sky masking (unlike
10283 // software Quake and software Quake2), so disable the sky masking
10284 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10285 // and skymasking also looks very bad when noclipping outside the
10286 // level, so don't use it then either.
10287 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10289 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10290 R_Mesh_ColorPointer(NULL, 0, 0);
10291 R_Mesh_ResetTextureState();
10292 if (skyrendermasked)
10294 R_SetupShader_DepthOrShadow();
10295 // depth-only (masking)
10296 GL_ColorMask(0,0,0,0);
10297 // just to make sure that braindead drivers don't draw
10298 // anything despite that colormask...
10299 GL_BlendFunc(GL_ZERO, GL_ONE);
10303 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10305 GL_BlendFunc(GL_ONE, GL_ZERO);
10307 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10308 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10309 if (skyrendermasked)
10310 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10312 R_Mesh_ResetTextureState();
10313 GL_Color(1, 1, 1, 1);
10316 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10317 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10318 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10320 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10323 // render screenspace normalmap to texture
10324 GL_DepthMask(true);
10325 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10326 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10328 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10330 // render water or distortion background, then blend surface on top
10331 GL_DepthMask(true);
10332 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10333 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10334 GL_DepthMask(false);
10335 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10336 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10340 // render surface normally
10341 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10342 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10343 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10344 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10345 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10346 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10348 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10352 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10354 // OpenGL 1.3 path - anything not completely ancient
10355 int texturesurfaceindex;
10356 qboolean applycolor;
10359 const texturelayer_t *layer;
10360 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10362 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10365 int layertexrgbscale;
10366 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10368 if (layerindex == 0)
10369 GL_AlphaTest(true);
10372 GL_AlphaTest(false);
10373 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10376 GL_DepthMask(layer->depthmask && writedepth);
10377 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10378 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10380 layertexrgbscale = 4;
10381 VectorScale(layer->color, 0.25f, layercolor);
10383 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10385 layertexrgbscale = 2;
10386 VectorScale(layer->color, 0.5f, layercolor);
10390 layertexrgbscale = 1;
10391 VectorScale(layer->color, 1.0f, layercolor);
10393 layercolor[3] = layer->color[3];
10394 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10395 R_Mesh_ColorPointer(NULL, 0, 0);
10396 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10397 switch (layer->type)
10399 case TEXTURELAYERTYPE_LITTEXTURE:
10400 // single-pass lightmapped texture with 2x rgbscale
10401 //R_Mesh_TexBind(0, r_texture_white);
10402 R_Mesh_TexMatrix(0, NULL);
10403 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10404 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10405 R_Mesh_TexBind(1, layer->texture);
10406 R_Mesh_TexMatrix(1, &layer->texmatrix);
10407 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10408 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10409 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10410 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10411 else if (rsurface.uselightmaptexture)
10412 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10414 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10416 case TEXTURELAYERTYPE_TEXTURE:
10417 // singletexture unlit texture with transparency support
10418 R_Mesh_TexBind(0, layer->texture);
10419 R_Mesh_TexMatrix(0, &layer->texmatrix);
10420 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10421 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10422 R_Mesh_TexBind(1, 0);
10423 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10424 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10426 case TEXTURELAYERTYPE_FOG:
10427 // singletexture fogging
10428 if (layer->texture)
10430 R_Mesh_TexBind(0, layer->texture);
10431 R_Mesh_TexMatrix(0, &layer->texmatrix);
10432 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10433 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10437 R_Mesh_TexBind(0, 0);
10438 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10440 R_Mesh_TexBind(1, 0);
10441 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10442 // generate a color array for the fog pass
10443 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10444 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10450 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10451 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)
10453 f = 1 - RSurf_FogVertex(v);
10454 c[0] = layercolor[0];
10455 c[1] = layercolor[1];
10456 c[2] = layercolor[2];
10457 c[3] = f * layercolor[3];
10460 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10463 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10467 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10469 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10470 GL_AlphaTest(false);
10474 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10476 // OpenGL 1.1 - crusty old voodoo path
10477 int texturesurfaceindex;
10480 const texturelayer_t *layer;
10481 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10483 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10485 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10487 if (layerindex == 0)
10488 GL_AlphaTest(true);
10491 GL_AlphaTest(false);
10492 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10495 GL_DepthMask(layer->depthmask && writedepth);
10496 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10497 R_Mesh_ColorPointer(NULL, 0, 0);
10498 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10499 switch (layer->type)
10501 case TEXTURELAYERTYPE_LITTEXTURE:
10502 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10504 // two-pass lit texture with 2x rgbscale
10505 // first the lightmap pass
10506 //R_Mesh_TexBind(0, r_texture_white);
10507 R_Mesh_TexMatrix(0, NULL);
10508 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10509 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10510 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10511 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10512 else if (rsurface.uselightmaptexture)
10513 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10515 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10516 // then apply the texture to it
10517 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10518 R_Mesh_TexBind(0, layer->texture);
10519 R_Mesh_TexMatrix(0, &layer->texmatrix);
10520 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10521 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10522 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);
10526 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10527 R_Mesh_TexBind(0, layer->texture);
10528 R_Mesh_TexMatrix(0, &layer->texmatrix);
10529 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10530 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10531 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10532 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);
10534 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);
10537 case TEXTURELAYERTYPE_TEXTURE:
10538 // singletexture unlit texture with transparency support
10539 R_Mesh_TexBind(0, layer->texture);
10540 R_Mesh_TexMatrix(0, &layer->texmatrix);
10541 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10542 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10543 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);
10545 case TEXTURELAYERTYPE_FOG:
10546 // singletexture fogging
10547 if (layer->texture)
10549 R_Mesh_TexBind(0, layer->texture);
10550 R_Mesh_TexMatrix(0, &layer->texmatrix);
10551 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10552 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10556 R_Mesh_TexBind(0, 0);
10557 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10559 // generate a color array for the fog pass
10560 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10561 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10567 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10568 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)
10570 f = 1 - RSurf_FogVertex(v);
10571 c[0] = layer->color[0];
10572 c[1] = layer->color[1];
10573 c[2] = layer->color[2];
10574 c[3] = f * layer->color[3];
10577 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10580 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10584 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10586 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10587 GL_AlphaTest(false);
10591 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10595 GL_AlphaTest(false);
10596 R_Mesh_ColorPointer(NULL, 0, 0);
10597 R_Mesh_ResetTextureState();
10598 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10600 if(rsurface.texture && rsurface.texture->currentskinframe)
10602 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10603 c[3] *= rsurface.texture->currentalpha;
10613 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10615 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10616 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10617 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10620 // brighten it up (as texture value 127 means "unlit")
10621 c[0] *= 2 * r_refdef.view.colorscale;
10622 c[1] *= 2 * r_refdef.view.colorscale;
10623 c[2] *= 2 * r_refdef.view.colorscale;
10625 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10626 c[3] *= r_wateralpha.value;
10628 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10630 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10631 GL_DepthMask(false);
10633 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10635 GL_BlendFunc(GL_ONE, GL_ONE);
10636 GL_DepthMask(false);
10638 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10640 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10641 GL_DepthMask(false);
10643 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10645 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10646 GL_DepthMask(false);
10650 GL_BlendFunc(GL_ONE, GL_ZERO);
10651 GL_DepthMask(writedepth);
10654 rsurface.lightmapcolor4f = NULL;
10656 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10658 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10660 rsurface.lightmapcolor4f = NULL;
10661 rsurface.lightmapcolor4f_bufferobject = 0;
10662 rsurface.lightmapcolor4f_bufferoffset = 0;
10664 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10666 qboolean applycolor = true;
10669 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10671 r_refdef.lightmapintensity = 1;
10672 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10673 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10677 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10679 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10680 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10681 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10684 if(!rsurface.lightmapcolor4f)
10685 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10687 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10688 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10689 if(r_refdef.fogenabled)
10690 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10692 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10693 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10696 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10699 RSurf_SetupDepthAndCulling();
10700 if (r_showsurfaces.integer == 3 && !prepass)
10702 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10705 switch (vid.renderpath)
10707 case RENDERPATH_GL20:
10708 case RENDERPATH_CGGL:
10709 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10711 case RENDERPATH_GL13:
10712 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10714 case RENDERPATH_GL11:
10715 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10721 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10724 RSurf_SetupDepthAndCulling();
10725 if (r_showsurfaces.integer == 3 && !prepass)
10727 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10730 switch (vid.renderpath)
10732 case RENDERPATH_GL20:
10733 case RENDERPATH_CGGL:
10734 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10736 case RENDERPATH_GL13:
10737 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10739 case RENDERPATH_GL11:
10740 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10746 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10749 int texturenumsurfaces, endsurface;
10750 texture_t *texture;
10751 const msurface_t *surface;
10752 const msurface_t *texturesurfacelist[256];
10754 // if the model is static it doesn't matter what value we give for
10755 // wantnormals and wanttangents, so this logic uses only rules applicable
10756 // to a model, knowing that they are meaningless otherwise
10757 if (ent == r_refdef.scene.worldentity)
10758 RSurf_ActiveWorldEntity();
10759 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10760 RSurf_ActiveModelEntity(ent, false, false, false);
10763 switch (vid.renderpath)
10765 case RENDERPATH_GL20:
10766 case RENDERPATH_CGGL:
10767 RSurf_ActiveModelEntity(ent, true, true, false);
10769 case RENDERPATH_GL13:
10770 case RENDERPATH_GL11:
10771 RSurf_ActiveModelEntity(ent, true, false, false);
10776 if (r_transparentdepthmasking.integer)
10778 qboolean setup = false;
10779 for (i = 0;i < numsurfaces;i = j)
10782 surface = rsurface.modelsurfaces + surfacelist[i];
10783 texture = surface->texture;
10784 rsurface.texture = R_GetCurrentTexture(texture);
10785 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10786 // scan ahead until we find a different texture
10787 endsurface = min(i + 1024, numsurfaces);
10788 texturenumsurfaces = 0;
10789 texturesurfacelist[texturenumsurfaces++] = surface;
10790 for (;j < endsurface;j++)
10792 surface = rsurface.modelsurfaces + surfacelist[j];
10793 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10795 texturesurfacelist[texturenumsurfaces++] = surface;
10797 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10799 // render the range of surfaces as depth
10803 GL_ColorMask(0,0,0,0);
10805 GL_DepthTest(true);
10806 GL_BlendFunc(GL_ONE, GL_ZERO);
10807 GL_DepthMask(true);
10808 GL_AlphaTest(false);
10809 R_Mesh_ColorPointer(NULL, 0, 0);
10810 R_Mesh_ResetTextureState();
10811 R_SetupShader_DepthOrShadow();
10813 RSurf_SetupDepthAndCulling();
10814 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10815 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10818 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10821 for (i = 0;i < numsurfaces;i = j)
10824 surface = rsurface.modelsurfaces + surfacelist[i];
10825 texture = surface->texture;
10826 rsurface.texture = R_GetCurrentTexture(texture);
10827 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10828 // scan ahead until we find a different texture
10829 endsurface = min(i + 1024, numsurfaces);
10830 texturenumsurfaces = 0;
10831 texturesurfacelist[texturenumsurfaces++] = surface;
10832 for (;j < endsurface;j++)
10834 surface = rsurface.modelsurfaces + surfacelist[j];
10835 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10837 texturesurfacelist[texturenumsurfaces++] = surface;
10839 // render the range of surfaces
10840 if (ent == r_refdef.scene.worldentity)
10841 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10843 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10845 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10846 GL_AlphaTest(false);
10849 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10851 // transparent surfaces get pushed off into the transparent queue
10852 int surfacelistindex;
10853 const msurface_t *surface;
10854 vec3_t tempcenter, center;
10855 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10857 surface = texturesurfacelist[surfacelistindex];
10858 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10859 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10860 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10861 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10862 if (queueentity->transparent_offset) // transparent offset
10864 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10865 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10866 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10868 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10872 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10874 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10878 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10880 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10882 RSurf_SetupDepthAndCulling();
10883 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10884 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10888 if (!rsurface.texture->currentnumlayers)
10890 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10891 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10893 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10895 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10897 RSurf_SetupDepthAndCulling();
10898 GL_AlphaTest(false);
10899 R_Mesh_ColorPointer(NULL, 0, 0);
10900 R_Mesh_ResetTextureState();
10901 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10902 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10903 GL_DepthMask(true);
10904 GL_BlendFunc(GL_ONE, GL_ZERO);
10905 GL_Color(0, 0, 0, 1);
10906 GL_DepthTest(writedepth);
10907 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10909 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10911 RSurf_SetupDepthAndCulling();
10912 GL_AlphaTest(false);
10913 R_Mesh_ColorPointer(NULL, 0, 0);
10914 R_Mesh_ResetTextureState();
10915 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10916 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10917 GL_DepthMask(true);
10918 GL_BlendFunc(GL_ONE, GL_ZERO);
10919 GL_DepthTest(true);
10920 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10922 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10923 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10924 else if (!rsurface.texture->currentnumlayers)
10926 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10928 // in the deferred case, transparent surfaces were queued during prepass
10929 if (!r_shadow_usingdeferredprepass)
10930 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10934 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10935 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10940 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10943 texture_t *texture;
10944 // break the surface list down into batches by texture and use of lightmapping
10945 for (i = 0;i < numsurfaces;i = j)
10948 // texture is the base texture pointer, rsurface.texture is the
10949 // current frame/skin the texture is directing us to use (for example
10950 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10951 // use skin 1 instead)
10952 texture = surfacelist[i]->texture;
10953 rsurface.texture = R_GetCurrentTexture(texture);
10954 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10955 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10957 // if this texture is not the kind we want, skip ahead to the next one
10958 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10962 // simply scan ahead until we find a different texture or lightmap state
10963 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10965 // render the range of surfaces
10966 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10970 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10975 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10977 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10979 RSurf_SetupDepthAndCulling();
10980 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10981 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10985 if (!rsurface.texture->currentnumlayers)
10987 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10988 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10990 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10992 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10994 RSurf_SetupDepthAndCulling();
10995 GL_AlphaTest(false);
10996 R_Mesh_ColorPointer(NULL, 0, 0);
10997 R_Mesh_ResetTextureState();
10998 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10999 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11000 GL_DepthMask(true);
11001 GL_BlendFunc(GL_ONE, GL_ZERO);
11002 GL_Color(0, 0, 0, 1);
11003 GL_DepthTest(writedepth);
11004 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11006 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11008 RSurf_SetupDepthAndCulling();
11009 GL_AlphaTest(false);
11010 R_Mesh_ColorPointer(NULL, 0, 0);
11011 R_Mesh_ResetTextureState();
11012 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11013 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11014 GL_DepthMask(true);
11015 GL_BlendFunc(GL_ONE, GL_ZERO);
11016 GL_DepthTest(true);
11017 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11019 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11020 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11021 else if (!rsurface.texture->currentnumlayers)
11023 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11025 // in the deferred case, transparent surfaces were queued during prepass
11026 if (!r_shadow_usingdeferredprepass)
11027 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11031 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11032 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11037 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11040 texture_t *texture;
11041 // break the surface list down into batches by texture and use of lightmapping
11042 for (i = 0;i < numsurfaces;i = j)
11045 // texture is the base texture pointer, rsurface.texture is the
11046 // current frame/skin the texture is directing us to use (for example
11047 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11048 // use skin 1 instead)
11049 texture = surfacelist[i]->texture;
11050 rsurface.texture = R_GetCurrentTexture(texture);
11051 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11052 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11054 // if this texture is not the kind we want, skip ahead to the next one
11055 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11059 // simply scan ahead until we find a different texture or lightmap state
11060 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11062 // render the range of surfaces
11063 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11067 float locboxvertex3f[6*4*3] =
11069 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11070 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11071 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11072 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11073 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11074 1,0,0, 0,0,0, 0,1,0, 1,1,0
11077 unsigned short locboxelements[6*2*3] =
11082 12,13,14, 12,14,15,
11083 16,17,18, 16,18,19,
11087 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11090 cl_locnode_t *loc = (cl_locnode_t *)ent;
11092 float vertex3f[6*4*3];
11094 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11095 GL_DepthMask(false);
11096 GL_DepthRange(0, 1);
11097 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11098 GL_DepthTest(true);
11099 GL_CullFace(GL_NONE);
11100 R_EntityMatrix(&identitymatrix);
11102 R_Mesh_VertexPointer(vertex3f, 0, 0);
11103 R_Mesh_ColorPointer(NULL, 0, 0);
11104 R_Mesh_ResetTextureState();
11105 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11107 i = surfacelist[0];
11108 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11109 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11110 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11111 surfacelist[0] < 0 ? 0.5f : 0.125f);
11113 if (VectorCompare(loc->mins, loc->maxs))
11115 VectorSet(size, 2, 2, 2);
11116 VectorMA(loc->mins, -0.5f, size, mins);
11120 VectorCopy(loc->mins, mins);
11121 VectorSubtract(loc->maxs, loc->mins, size);
11124 for (i = 0;i < 6*4*3;)
11125 for (j = 0;j < 3;j++, i++)
11126 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11128 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11131 void R_DrawLocs(void)
11134 cl_locnode_t *loc, *nearestloc;
11136 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11137 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11139 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11140 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11144 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11146 if (decalsystem->decals)
11147 Mem_Free(decalsystem->decals);
11148 memset(decalsystem, 0, sizeof(*decalsystem));
11151 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)
11154 tridecal_t *decals;
11158 // expand or initialize the system
11159 if (decalsystem->maxdecals <= decalsystem->numdecals)
11161 decalsystem_t old = *decalsystem;
11162 qboolean useshortelements;
11163 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11164 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11165 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)));
11166 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11167 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11168 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11169 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11170 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11171 if (decalsystem->numdecals)
11172 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11174 Mem_Free(old.decals);
11175 for (i = 0;i < decalsystem->maxdecals*3;i++)
11176 decalsystem->element3i[i] = i;
11177 if (useshortelements)
11178 for (i = 0;i < decalsystem->maxdecals*3;i++)
11179 decalsystem->element3s[i] = i;
11182 // grab a decal and search for another free slot for the next one
11183 maxdecals = decalsystem->maxdecals;
11184 decals = decalsystem->decals;
11185 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11186 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11188 decalsystem->freedecal = i;
11189 if (decalsystem->numdecals <= i)
11190 decalsystem->numdecals = i + 1;
11192 // initialize the decal
11194 decal->triangleindex = triangleindex;
11195 decal->surfaceindex = surfaceindex;
11196 decal->decalsequence = decalsequence;
11197 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11198 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11199 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11200 decal->color4ub[0][3] = 255;
11201 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11202 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11203 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11204 decal->color4ub[1][3] = 255;
11205 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11206 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11207 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11208 decal->color4ub[2][3] = 255;
11209 decal->vertex3f[0][0] = v0[0];
11210 decal->vertex3f[0][1] = v0[1];
11211 decal->vertex3f[0][2] = v0[2];
11212 decal->vertex3f[1][0] = v1[0];
11213 decal->vertex3f[1][1] = v1[1];
11214 decal->vertex3f[1][2] = v1[2];
11215 decal->vertex3f[2][0] = v2[0];
11216 decal->vertex3f[2][1] = v2[1];
11217 decal->vertex3f[2][2] = v2[2];
11218 decal->texcoord2f[0][0] = t0[0];
11219 decal->texcoord2f[0][1] = t0[1];
11220 decal->texcoord2f[1][0] = t1[0];
11221 decal->texcoord2f[1][1] = t1[1];
11222 decal->texcoord2f[2][0] = t2[0];
11223 decal->texcoord2f[2][1] = t2[1];
11226 extern cvar_t cl_decals_bias;
11227 extern cvar_t cl_decals_models;
11228 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11229 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)
11231 matrix4x4_t projection;
11232 decalsystem_t *decalsystem;
11235 const float *vertex3f;
11236 const msurface_t *surface;
11237 const msurface_t *surfaces;
11238 const int *surfacelist;
11239 const texture_t *texture;
11242 int numsurfacelist;
11243 int surfacelistindex;
11246 int decalsurfaceindex;
11251 float localorigin[3];
11252 float localnormal[3];
11253 float localmins[3];
11254 float localmaxs[3];
11261 float planes[6][4];
11263 float points[2][9][3];
11267 decalsystem = &ent->decalsystem;
11268 model = ent->model;
11269 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11271 R_DecalSystem_Reset(&ent->decalsystem);
11275 if (!model->brush.data_nodes && !cl_decals_models.integer)
11277 if (decalsystem->model)
11278 R_DecalSystem_Reset(decalsystem);
11282 if (decalsystem->model != model)
11283 R_DecalSystem_Reset(decalsystem);
11284 decalsystem->model = model;
11286 RSurf_ActiveModelEntity(ent, false, false, false);
11288 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11289 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11290 VectorNormalize(localnormal);
11291 localsize = worldsize*rsurface.inversematrixscale;
11292 ilocalsize = 1.0f / localsize;
11293 localmins[0] = localorigin[0] - localsize;
11294 localmins[1] = localorigin[1] - localsize;
11295 localmins[2] = localorigin[2] - localsize;
11296 localmaxs[0] = localorigin[0] + localsize;
11297 localmaxs[1] = localorigin[1] + localsize;
11298 localmaxs[2] = localorigin[2] + localsize;
11300 //VectorCopy(localnormal, planes[4]);
11301 //VectorVectors(planes[4], planes[2], planes[0]);
11302 AnglesFromVectors(angles, localnormal, NULL, false);
11303 AngleVectors(angles, planes[0], planes[2], planes[4]);
11304 VectorNegate(planes[0], planes[1]);
11305 VectorNegate(planes[2], planes[3]);
11306 VectorNegate(planes[4], planes[5]);
11307 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11308 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11309 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11310 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11311 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11312 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11317 matrix4x4_t forwardprojection;
11318 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11319 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11324 float projectionvector[4][3];
11325 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11326 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11327 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11328 projectionvector[0][0] = planes[0][0] * ilocalsize;
11329 projectionvector[0][1] = planes[1][0] * ilocalsize;
11330 projectionvector[0][2] = planes[2][0] * ilocalsize;
11331 projectionvector[1][0] = planes[0][1] * ilocalsize;
11332 projectionvector[1][1] = planes[1][1] * ilocalsize;
11333 projectionvector[1][2] = planes[2][1] * ilocalsize;
11334 projectionvector[2][0] = planes[0][2] * ilocalsize;
11335 projectionvector[2][1] = planes[1][2] * ilocalsize;
11336 projectionvector[2][2] = planes[2][2] * ilocalsize;
11337 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11338 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11339 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11340 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11344 dynamic = model->surfmesh.isanimated;
11345 vertex3f = rsurface.modelvertex3f;
11346 numsurfacelist = model->nummodelsurfaces;
11347 surfacelist = model->sortedmodelsurfaces;
11348 surfaces = model->data_surfaces;
11349 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11351 surfaceindex = surfacelist[surfacelistindex];
11352 surface = surfaces + surfaceindex;
11353 // skip transparent surfaces
11354 texture = surface->texture;
11355 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11357 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11359 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11361 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11362 numvertices = surface->num_vertices;
11363 numtriangles = surface->num_triangles;
11364 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11366 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11368 index = 3*e[cornerindex];
11369 VectorCopy(vertex3f + index, v[cornerindex]);
11372 //TriangleNormal(v[0], v[1], v[2], normal);
11373 //if (DotProduct(normal, localnormal) < 0.0f)
11375 // clip by each of the box planes formed from the projection matrix
11376 // if anything survives, we emit the decal
11377 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]);
11380 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]);
11383 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]);
11386 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]);
11389 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]);
11392 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]);
11395 // some part of the triangle survived, so we have to accept it...
11398 // dynamic always uses the original triangle
11400 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11402 index = 3*e[cornerindex];
11403 VectorCopy(vertex3f + index, v[cornerindex]);
11406 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11408 // convert vertex positions to texcoords
11409 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11410 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11411 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11412 // calculate distance fade from the projection origin
11413 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11414 f = bound(0.0f, f, 1.0f);
11415 c[cornerindex][0] = r * f;
11416 c[cornerindex][1] = g * f;
11417 c[cornerindex][2] = b * f;
11418 c[cornerindex][3] = 1.0f;
11419 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11422 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);
11424 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11425 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);
11430 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11431 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)
11433 int renderentityindex;
11434 float worldmins[3];
11435 float worldmaxs[3];
11436 entity_render_t *ent;
11438 if (!cl_decals_newsystem.integer)
11441 worldmins[0] = worldorigin[0] - worldsize;
11442 worldmins[1] = worldorigin[1] - worldsize;
11443 worldmins[2] = worldorigin[2] - worldsize;
11444 worldmaxs[0] = worldorigin[0] + worldsize;
11445 worldmaxs[1] = worldorigin[1] + worldsize;
11446 worldmaxs[2] = worldorigin[2] + worldsize;
11448 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11450 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11452 ent = r_refdef.scene.entities[renderentityindex];
11453 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11456 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11460 typedef struct r_decalsystem_splatqueue_s
11462 vec3_t worldorigin;
11463 vec3_t worldnormal;
11469 r_decalsystem_splatqueue_t;
11471 int r_decalsystem_numqueued = 0;
11472 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11474 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)
11476 r_decalsystem_splatqueue_t *queue;
11478 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11481 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11482 VectorCopy(worldorigin, queue->worldorigin);
11483 VectorCopy(worldnormal, queue->worldnormal);
11484 Vector4Set(queue->color, r, g, b, a);
11485 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11486 queue->worldsize = worldsize;
11487 queue->decalsequence = cl.decalsequence++;
11490 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11493 r_decalsystem_splatqueue_t *queue;
11495 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11496 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);
11497 r_decalsystem_numqueued = 0;
11500 extern cvar_t cl_decals_max;
11501 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11504 decalsystem_t *decalsystem = &ent->decalsystem;
11511 if (!decalsystem->numdecals)
11514 if (r_showsurfaces.integer)
11517 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11519 R_DecalSystem_Reset(decalsystem);
11523 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11524 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11526 if (decalsystem->lastupdatetime)
11527 frametime = (cl.time - decalsystem->lastupdatetime);
11530 decalsystem->lastupdatetime = cl.time;
11531 decal = decalsystem->decals;
11532 numdecals = decalsystem->numdecals;
11534 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11536 if (decal->color4ub[0][3])
11538 decal->lived += frametime;
11539 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11541 memset(decal, 0, sizeof(*decal));
11542 if (decalsystem->freedecal > i)
11543 decalsystem->freedecal = i;
11547 decal = decalsystem->decals;
11548 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11551 // collapse the array by shuffling the tail decals into the gaps
11554 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11555 decalsystem->freedecal++;
11556 if (decalsystem->freedecal == numdecals)
11558 decal[decalsystem->freedecal] = decal[--numdecals];
11561 decalsystem->numdecals = numdecals;
11563 if (numdecals <= 0)
11565 // if there are no decals left, reset decalsystem
11566 R_DecalSystem_Reset(decalsystem);
11570 extern skinframe_t *decalskinframe;
11571 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11574 decalsystem_t *decalsystem = &ent->decalsystem;
11584 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11587 numdecals = decalsystem->numdecals;
11591 if (r_showsurfaces.integer)
11594 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11596 R_DecalSystem_Reset(decalsystem);
11600 // if the model is static it doesn't matter what value we give for
11601 // wantnormals and wanttangents, so this logic uses only rules applicable
11602 // to a model, knowing that they are meaningless otherwise
11603 if (ent == r_refdef.scene.worldentity)
11604 RSurf_ActiveWorldEntity();
11606 RSurf_ActiveModelEntity(ent, false, false, false);
11608 decalsystem->lastupdatetime = cl.time;
11609 decal = decalsystem->decals;
11611 fadedelay = cl_decals_time.value;
11612 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11614 // update vertex positions for animated models
11615 v3f = decalsystem->vertex3f;
11616 c4f = decalsystem->color4f;
11617 t2f = decalsystem->texcoord2f;
11618 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11620 if (!decal->color4ub[0][3])
11623 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11626 // update color values for fading decals
11627 if (decal->lived >= cl_decals_time.value)
11629 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11630 alpha *= (1.0f/255.0f);
11633 alpha = 1.0f/255.0f;
11635 c4f[ 0] = decal->color4ub[0][0] * alpha;
11636 c4f[ 1] = decal->color4ub[0][1] * alpha;
11637 c4f[ 2] = decal->color4ub[0][2] * alpha;
11639 c4f[ 4] = decal->color4ub[1][0] * alpha;
11640 c4f[ 5] = decal->color4ub[1][1] * alpha;
11641 c4f[ 6] = decal->color4ub[1][2] * alpha;
11643 c4f[ 8] = decal->color4ub[2][0] * alpha;
11644 c4f[ 9] = decal->color4ub[2][1] * alpha;
11645 c4f[10] = decal->color4ub[2][2] * alpha;
11648 t2f[0] = decal->texcoord2f[0][0];
11649 t2f[1] = decal->texcoord2f[0][1];
11650 t2f[2] = decal->texcoord2f[1][0];
11651 t2f[3] = decal->texcoord2f[1][1];
11652 t2f[4] = decal->texcoord2f[2][0];
11653 t2f[5] = decal->texcoord2f[2][1];
11655 // update vertex positions for animated models
11656 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11658 e = rsurface.modelelement3i + 3*decal->triangleindex;
11659 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11660 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11661 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11665 VectorCopy(decal->vertex3f[0], v3f);
11666 VectorCopy(decal->vertex3f[1], v3f + 3);
11667 VectorCopy(decal->vertex3f[2], v3f + 6);
11678 r_refdef.stats.drawndecals += numtris;
11680 if (r_refdef.fogenabled)
11682 switch(vid.renderpath)
11684 case RENDERPATH_GL20:
11685 case RENDERPATH_CGGL:
11686 case RENDERPATH_GL13:
11687 case RENDERPATH_GL11:
11688 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11690 alpha = RSurf_FogVertex(v3f);
11699 // now render the decals all at once
11700 // (this assumes they all use one particle font texture!)
11701 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);
11702 R_Mesh_ResetTextureState();
11703 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11704 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11705 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11706 GL_DepthMask(false);
11707 GL_DepthRange(0, 1);
11708 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11709 GL_DepthTest(true);
11710 GL_CullFace(GL_NONE);
11711 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11712 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11713 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11717 static void R_DrawModelDecals(void)
11721 // fade faster when there are too many decals
11722 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11723 for (i = 0;i < r_refdef.scene.numentities;i++)
11724 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11726 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11727 for (i = 0;i < r_refdef.scene.numentities;i++)
11728 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11729 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11731 R_DecalSystem_ApplySplatEntitiesQueue();
11733 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11734 for (i = 0;i < r_refdef.scene.numentities;i++)
11735 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11737 r_refdef.stats.totaldecals += numdecals;
11739 if (r_showsurfaces.integer)
11742 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11744 for (i = 0;i < r_refdef.scene.numentities;i++)
11746 if (!r_refdef.viewcache.entityvisible[i])
11748 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11749 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11753 void R_DrawDebugModel(void)
11755 entity_render_t *ent = rsurface.entity;
11756 int i, j, k, l, flagsmask;
11757 const int *elements;
11759 const msurface_t *surface;
11760 dp_model_t *model = ent->model;
11763 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11765 R_Mesh_ColorPointer(NULL, 0, 0);
11766 R_Mesh_ResetTextureState();
11767 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11768 GL_DepthRange(0, 1);
11769 GL_DepthTest(!r_showdisabledepthtest.integer);
11770 GL_DepthMask(false);
11771 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11773 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11775 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11776 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11778 if (brush->colbrushf && brush->colbrushf->numtriangles)
11780 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11781 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);
11782 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11785 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11787 if (surface->num_collisiontriangles)
11789 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11790 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);
11791 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11796 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11798 if (r_showtris.integer || r_shownormals.integer)
11800 if (r_showdisabledepthtest.integer)
11802 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11803 GL_DepthMask(false);
11807 GL_BlendFunc(GL_ONE, GL_ZERO);
11808 GL_DepthMask(true);
11810 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11812 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11814 rsurface.texture = R_GetCurrentTexture(surface->texture);
11815 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11817 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11818 if (r_showtris.value > 0)
11820 if (!rsurface.texture->currentlayers->depthmask)
11821 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11822 else if (ent == r_refdef.scene.worldentity)
11823 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11825 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11826 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11827 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11828 R_Mesh_ColorPointer(NULL, 0, 0);
11829 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11830 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11831 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11832 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);
11833 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11836 if (r_shownormals.value < 0)
11838 qglBegin(GL_LINES);
11839 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11841 VectorCopy(rsurface.vertex3f + l * 3, v);
11842 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11843 qglVertex3f(v[0], v[1], v[2]);
11844 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11845 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11846 qglVertex3f(v[0], v[1], v[2]);
11851 if (r_shownormals.value > 0)
11853 qglBegin(GL_LINES);
11854 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11856 VectorCopy(rsurface.vertex3f + l * 3, v);
11857 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11858 qglVertex3f(v[0], v[1], v[2]);
11859 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11860 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11861 qglVertex3f(v[0], v[1], v[2]);
11865 qglBegin(GL_LINES);
11866 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11868 VectorCopy(rsurface.vertex3f + l * 3, v);
11869 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11870 qglVertex3f(v[0], v[1], v[2]);
11871 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11872 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11873 qglVertex3f(v[0], v[1], v[2]);
11877 qglBegin(GL_LINES);
11878 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11880 VectorCopy(rsurface.vertex3f + l * 3, v);
11881 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11882 qglVertex3f(v[0], v[1], v[2]);
11883 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11884 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11885 qglVertex3f(v[0], v[1], v[2]);
11892 rsurface.texture = NULL;
11896 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11897 int r_maxsurfacelist = 0;
11898 const msurface_t **r_surfacelist = NULL;
11899 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11901 int i, j, endj, f, flagsmask;
11903 dp_model_t *model = r_refdef.scene.worldmodel;
11904 msurface_t *surfaces;
11905 unsigned char *update;
11906 int numsurfacelist = 0;
11910 if (r_maxsurfacelist < model->num_surfaces)
11912 r_maxsurfacelist = model->num_surfaces;
11914 Mem_Free((msurface_t**)r_surfacelist);
11915 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11918 RSurf_ActiveWorldEntity();
11920 surfaces = model->data_surfaces;
11921 update = model->brushq1.lightmapupdateflags;
11923 // update light styles on this submodel
11924 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11926 model_brush_lightstyleinfo_t *style;
11927 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11929 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11931 int *list = style->surfacelist;
11932 style->value = r_refdef.scene.lightstylevalue[style->style];
11933 for (j = 0;j < style->numsurfaces;j++)
11934 update[list[j]] = true;
11939 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11943 R_DrawDebugModel();
11944 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11950 rsurface.uselightmaptexture = false;
11951 rsurface.texture = NULL;
11952 rsurface.rtlight = NULL;
11953 numsurfacelist = 0;
11954 // add visible surfaces to draw list
11955 for (i = 0;i < model->nummodelsurfaces;i++)
11957 j = model->sortedmodelsurfaces[i];
11958 if (r_refdef.viewcache.world_surfacevisible[j])
11959 r_surfacelist[numsurfacelist++] = surfaces + j;
11961 // update lightmaps if needed
11962 if (model->brushq1.firstrender)
11964 model->brushq1.firstrender = false;
11965 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11967 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11971 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11972 if (r_refdef.viewcache.world_surfacevisible[j])
11974 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11976 // don't do anything if there were no surfaces
11977 if (!numsurfacelist)
11979 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11982 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11983 GL_AlphaTest(false);
11985 // add to stats if desired
11986 if (r_speeds.integer && !skysurfaces && !depthonly)
11988 r_refdef.stats.world_surfaces += numsurfacelist;
11989 for (j = 0;j < numsurfacelist;j++)
11990 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11993 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11996 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11998 int i, j, endj, f, flagsmask;
12000 dp_model_t *model = ent->model;
12001 msurface_t *surfaces;
12002 unsigned char *update;
12003 int numsurfacelist = 0;
12007 if (r_maxsurfacelist < model->num_surfaces)
12009 r_maxsurfacelist = model->num_surfaces;
12011 Mem_Free((msurface_t **)r_surfacelist);
12012 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12015 // if the model is static it doesn't matter what value we give for
12016 // wantnormals and wanttangents, so this logic uses only rules applicable
12017 // to a model, knowing that they are meaningless otherwise
12018 if (ent == r_refdef.scene.worldentity)
12019 RSurf_ActiveWorldEntity();
12020 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12021 RSurf_ActiveModelEntity(ent, false, false, false);
12023 RSurf_ActiveModelEntity(ent, true, true, true);
12024 else if (depthonly)
12025 RSurf_ActiveModelEntity(ent, false, false, false);
12028 switch (vid.renderpath)
12030 case RENDERPATH_GL20:
12031 case RENDERPATH_CGGL:
12032 RSurf_ActiveModelEntity(ent, true, true, false);
12034 case RENDERPATH_GL13:
12035 case RENDERPATH_GL11:
12036 RSurf_ActiveModelEntity(ent, true, false, false);
12041 surfaces = model->data_surfaces;
12042 update = model->brushq1.lightmapupdateflags;
12044 // update light styles
12045 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12047 model_brush_lightstyleinfo_t *style;
12048 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12050 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12052 int *list = style->surfacelist;
12053 style->value = r_refdef.scene.lightstylevalue[style->style];
12054 for (j = 0;j < style->numsurfaces;j++)
12055 update[list[j]] = true;
12060 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12064 R_DrawDebugModel();
12065 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12071 rsurface.uselightmaptexture = false;
12072 rsurface.texture = NULL;
12073 rsurface.rtlight = NULL;
12074 numsurfacelist = 0;
12075 // add visible surfaces to draw list
12076 for (i = 0;i < model->nummodelsurfaces;i++)
12077 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12078 // don't do anything if there were no surfaces
12079 if (!numsurfacelist)
12081 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12084 // update lightmaps if needed
12088 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12093 R_BuildLightMap(ent, surfaces + j);
12098 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12100 R_BuildLightMap(ent, surfaces + j);
12101 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12102 GL_AlphaTest(false);
12104 // add to stats if desired
12105 if (r_speeds.integer && !skysurfaces && !depthonly)
12107 r_refdef.stats.entities_surfaces += numsurfacelist;
12108 for (j = 0;j < numsurfacelist;j++)
12109 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12112 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12115 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12117 static texture_t texture;
12118 static msurface_t surface;
12119 const msurface_t *surfacelist = &surface;
12121 // fake enough texture and surface state to render this geometry
12123 texture.update_lastrenderframe = -1; // regenerate this texture
12124 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12125 texture.currentskinframe = skinframe;
12126 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12127 texture.specularscalemod = 1;
12128 texture.specularpowermod = 1;
12130 surface.texture = &texture;
12131 surface.num_triangles = numtriangles;
12132 surface.num_firsttriangle = firsttriangle;
12133 surface.num_vertices = numvertices;
12134 surface.num_firstvertex = firstvertex;
12137 rsurface.texture = R_GetCurrentTexture(surface.texture);
12138 rsurface.uselightmaptexture = false;
12139 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12142 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)
12144 static msurface_t surface;
12145 const msurface_t *surfacelist = &surface;
12147 // fake enough texture and surface state to render this geometry
12149 surface.texture = texture;
12150 surface.num_triangles = numtriangles;
12151 surface.num_firsttriangle = firsttriangle;
12152 surface.num_vertices = numvertices;
12153 surface.num_firstvertex = firstvertex;
12156 rsurface.texture = R_GetCurrentTexture(surface.texture);
12157 rsurface.uselightmaptexture = false;
12158 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);