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"
31 mempool_t *r_main_mempool;
32 rtexturepool_t *r_main_texturepool;
34 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
36 static qboolean r_loadnormalmap;
37 static qboolean r_loadgloss;
39 static qboolean r_loaddds;
40 static qboolean r_savedds;
47 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
48 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
49 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
50 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
51 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)"};
52 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
53 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
54 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
56 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
57 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"};
58 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
59 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)"};
60 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
62 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"};
63 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
64 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
65 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
66 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
67 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
68 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)"};
69 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
70 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
71 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"};
72 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"};
73 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
74 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"};
75 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"};
76 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"};
77 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
78 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
79 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
80 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
81 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
82 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)"};
83 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)"};
84 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
85 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
86 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
87 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
88 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
89 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
90 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
91 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."};
92 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
93 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
94 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
95 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."};
96 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
97 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
98 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
99 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
100 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"};
101 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"};
102 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
103 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
104 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
105 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
106 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"};
108 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
109 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
110 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
111 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
112 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
113 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
114 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
115 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
117 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)"};
118 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"};
120 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
121 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
122 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
123 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
124 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
126 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
127 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
128 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
130 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)"};
131 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
132 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
133 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
134 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
135 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)"};
136 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)"};
137 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)"};
138 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)"};
139 //cvar_t r_glsl_postprocess_sobel = {CVAR_SAVE, "r_glsl_postprocess_sobel", "0", "1 = use the sobel operator on the final output (this causes grey-scaling), 2 = combine sobel and blur"};
141 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)"};
142 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
143 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"};
144 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
145 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
147 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
148 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
149 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
150 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
152 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
153 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
154 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
155 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
156 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
157 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
158 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
160 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
161 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
162 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
163 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)"};
165 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"};
167 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"};
169 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
171 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
172 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
173 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"};
174 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
175 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
176 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
177 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
178 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
180 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
182 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)"};
184 extern cvar_t v_glslgamma;
186 extern qboolean v_flipped_state;
188 static struct r_bloomstate_s
193 int bloomwidth, bloomheight;
195 int screentexturewidth, screentextureheight;
196 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
198 int bloomtexturewidth, bloomtextureheight;
199 rtexture_t *texture_bloom;
201 // arrays for rendering the screen passes
202 float screentexcoord2f[8];
203 float bloomtexcoord2f[8];
204 float offsettexcoord2f[8];
206 r_viewport_t viewport;
210 r_waterstate_t r_waterstate;
212 /// shadow volume bsp struct with automatically growing nodes buffer
215 rtexture_t *r_texture_blanknormalmap;
216 rtexture_t *r_texture_white;
217 rtexture_t *r_texture_grey128;
218 rtexture_t *r_texture_black;
219 rtexture_t *r_texture_notexture;
220 rtexture_t *r_texture_whitecube;
221 rtexture_t *r_texture_normalizationcube;
222 rtexture_t *r_texture_fogattenuation;
223 rtexture_t *r_texture_fogheighttexture;
224 rtexture_t *r_texture_gammaramps;
225 unsigned int r_texture_gammaramps_serial;
226 //rtexture_t *r_texture_fogintensity;
227 rtexture_t *r_texture_reflectcube;
229 // TODO: hash lookups?
230 typedef struct cubemapinfo_s
237 int r_texture_numcubemaps;
238 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
240 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
241 unsigned int r_numqueries;
242 unsigned int r_maxqueries;
244 typedef struct r_qwskincache_s
246 char name[MAX_QPATH];
247 skinframe_t *skinframe;
251 static r_qwskincache_t *r_qwskincache;
252 static int r_qwskincache_size;
254 /// vertex coordinates for a quad that covers the screen exactly
255 const float r_screenvertex3f[12] =
263 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
266 for (i = 0;i < verts;i++)
277 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
280 for (i = 0;i < verts;i++)
290 // FIXME: move this to client?
293 if (gamemode == GAME_NEHAHRA)
295 Cvar_Set("gl_fogenable", "0");
296 Cvar_Set("gl_fogdensity", "0.2");
297 Cvar_Set("gl_fogred", "0.3");
298 Cvar_Set("gl_foggreen", "0.3");
299 Cvar_Set("gl_fogblue", "0.3");
301 r_refdef.fog_density = 0;
302 r_refdef.fog_red = 0;
303 r_refdef.fog_green = 0;
304 r_refdef.fog_blue = 0;
305 r_refdef.fog_alpha = 1;
306 r_refdef.fog_start = 0;
307 r_refdef.fog_end = 16384;
308 r_refdef.fog_height = 1<<30;
309 r_refdef.fog_fadedepth = 128;
310 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
313 static void R_BuildBlankTextures(void)
315 unsigned char data[4];
316 data[2] = 128; // normal X
317 data[1] = 128; // normal Y
318 data[0] = 255; // normal Z
319 data[3] = 128; // height
320 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
325 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
330 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
335 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
338 static void R_BuildNoTexture(void)
341 unsigned char pix[16][16][4];
342 // this makes a light grey/dark grey checkerboard texture
343 for (y = 0;y < 16;y++)
345 for (x = 0;x < 16;x++)
347 if ((y < 8) ^ (x < 8))
363 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
366 static void R_BuildWhiteCube(void)
368 unsigned char data[6*1*1*4];
369 memset(data, 255, sizeof(data));
370 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
373 static void R_BuildNormalizationCube(void)
377 vec_t s, t, intensity;
380 data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
381 for (side = 0;side < 6;side++)
383 for (y = 0;y < NORMSIZE;y++)
385 for (x = 0;x < NORMSIZE;x++)
387 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
388 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
423 intensity = 127.0f / sqrt(DotProduct(v, v));
424 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
425 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
426 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
427 data[((side*64+y)*64+x)*4+3] = 255;
431 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
435 static void R_BuildFogTexture(void)
439 unsigned char data1[FOGWIDTH][4];
440 //unsigned char data2[FOGWIDTH][4];
443 r_refdef.fogmasktable_start = r_refdef.fog_start;
444 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
445 r_refdef.fogmasktable_range = r_refdef.fogrange;
446 r_refdef.fogmasktable_density = r_refdef.fog_density;
448 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
449 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
451 d = (x * r - r_refdef.fogmasktable_start);
452 if(developer_extra.integer)
453 Con_DPrintf("%f ", d);
455 if (r_fog_exp2.integer)
456 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
458 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
459 if(developer_extra.integer)
460 Con_DPrintf(" : %f ", alpha);
461 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
462 if(developer_extra.integer)
463 Con_DPrintf(" = %f\n", alpha);
464 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
467 for (x = 0;x < FOGWIDTH;x++)
469 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
474 //data2[x][0] = 255 - b;
475 //data2[x][1] = 255 - b;
476 //data2[x][2] = 255 - b;
479 if (r_texture_fogattenuation)
481 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
482 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
486 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);
487 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
491 static void R_BuildFogHeightTexture(void)
493 unsigned char *inpixels;
501 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
502 if (r_refdef.fogheighttexturename[0])
503 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false);
506 r_refdef.fog_height_tablesize = 0;
507 if (r_texture_fogheighttexture)
508 R_FreeTexture(r_texture_fogheighttexture);
509 r_texture_fogheighttexture = NULL;
510 if (r_refdef.fog_height_table2d)
511 Mem_Free(r_refdef.fog_height_table2d);
512 r_refdef.fog_height_table2d = NULL;
513 if (r_refdef.fog_height_table1d)
514 Mem_Free(r_refdef.fog_height_table1d);
515 r_refdef.fog_height_table1d = NULL;
519 r_refdef.fog_height_tablesize = size;
520 r_refdef.fog_height_table1d = Mem_Alloc(r_main_mempool, size * 4);
521 r_refdef.fog_height_table2d = Mem_Alloc(r_main_mempool, size * size * 4);
522 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
524 // LordHavoc: now the magic - what is that table2d for? it is a cooked
525 // average fog color table accounting for every fog layer between a point
526 // and the camera. (Note: attenuation is handled separately!)
527 for (y = 0;y < size;y++)
529 for (x = 0;x < size;x++)
535 for (j = x;j <= y;j++)
537 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
543 for (j = x;j >= y;j--)
545 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
550 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
551 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
552 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
553 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
556 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, NULL);
559 //=======================================================================================================================================================
561 static const char *builtinshaderstring =
562 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
563 "// written by Forest 'LordHavoc' Hale\n"
564 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
566 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
569 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
570 "#define USELIGHTMAP\n"
572 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
573 "#define USEEYEVECTOR\n"
576 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
577 "# extension GL_ARB_texture_rectangle : enable\n"
580 "#ifdef USESHADOWMAP2D\n"
581 "# ifdef GL_EXT_gpu_shader4\n"
582 "# extension GL_EXT_gpu_shader4 : enable\n"
584 "# ifdef GL_ARB_texture_gather\n"
585 "# extension GL_ARB_texture_gather : enable\n"
587 "# ifdef GL_AMD_texture_texture4\n"
588 "# extension GL_AMD_texture_texture4 : enable\n"
593 "#ifdef USESHADOWMAPCUBE\n"
594 "# extension GL_EXT_gpu_shader4 : enable\n"
597 "//#ifdef USESHADOWSAMPLER\n"
598 "//# extension GL_ARB_shadow : enable\n"
601 "//#ifdef __GLSL_CG_DATA_TYPES\n"
602 "//# define myhalf half\n"
603 "//# define myhalf2 half2\n"
604 "//# define myhalf3 half3\n"
605 "//# define myhalf4 half4\n"
607 "# define myhalf float\n"
608 "# define myhalf2 vec2\n"
609 "# define myhalf3 vec3\n"
610 "# define myhalf4 vec4\n"
613 "#ifdef VERTEX_SHADER\n"
614 "uniform mat4 ModelViewProjectionMatrix;\n"
617 "#ifdef MODE_DEPTH_OR_SHADOW\n"
618 "#ifdef VERTEX_SHADER\n"
621 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
624 "#else // !MODE_DEPTH_ORSHADOW\n"
629 "#ifdef MODE_SHOWDEPTH\n"
630 "#ifdef VERTEX_SHADER\n"
633 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
634 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
638 "#ifdef FRAGMENT_SHADER\n"
641 " gl_FragColor = gl_Color;\n"
644 "#else // !MODE_SHOWDEPTH\n"
649 "#ifdef MODE_POSTPROCESS\n"
650 "varying vec2 TexCoord1;\n"
651 "varying vec2 TexCoord2;\n"
653 "#ifdef VERTEX_SHADER\n"
656 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
657 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
659 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
664 "#ifdef FRAGMENT_SHADER\n"
665 "uniform sampler2D Texture_First;\n"
667 "uniform sampler2D Texture_Second;\n"
669 "#ifdef USEGAMMARAMPS\n"
670 "uniform sampler2D Texture_GammaRamps;\n"
672 "#ifdef USESATURATION\n"
673 "uniform float Saturation;\n"
675 "#ifdef USEVIEWTINT\n"
676 "uniform vec4 ViewTintColor;\n"
678 "//uncomment these if you want to use them:\n"
679 "uniform vec4 UserVec1;\n"
680 "//uniform float UseSobel;\n"
681 "uniform vec4 UserVec2;\n"
682 "// uniform vec4 UserVec3;\n"
683 "// uniform vec4 UserVec4;\n"
684 "// uniform float ClientTime;\n"
685 "uniform vec2 PixelSize;\n"
688 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
690 " gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
692 "#ifdef USEVIEWTINT\n"
693 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
696 "#ifdef USEPOSTPROCESSING\n"
697 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
698 "// 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"
699 " vec3 sobel = vec3(1.0);\n"
700 " // vec2 ts = textureSize(Texture_First, 0);\n"
701 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
702 " vec2 px = PixelSize;\n"
703 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
704 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
705 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
706 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
707 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
708 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
709 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
710 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
711 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
712 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
713 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
714 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
715 " float px1 = -1.0 * (0.30*x1.r + 0.59*x1.g + 0.11*x1.b);\n"
716 " float px2 = -2.0 * (0.30*x2.r + 0.59*x2.g + 0.11*x2.b);\n"
717 " float px3 = -1.0 * (0.30*x3.r + 0.59*x3.g + 0.11*x3.b);\n"
718 " float px4 = 1.0 * (0.30*x4.r + 0.59*x4.g + 0.11*x4.b);\n"
719 " float px5 = 2.0 * (0.30*x5.r + 0.59*x5.g + 0.11*x5.b);\n"
720 " float px6 = 1.0 * (0.30*x6.r + 0.59*x6.g + 0.11*x6.b);\n"
721 " float py1 = -1.0 * (0.30*y1.r + 0.59*y1.g + 0.11*y1.b);\n"
722 " float py2 = -2.0 * (0.30*y2.r + 0.59*y2.g + 0.11*y2.b);\n"
723 " float py3 = -1.0 * (0.30*y3.r + 0.59*y3.g + 0.11*y3.b);\n"
724 " float py4 = 1.0 * (0.30*y4.r + 0.59*y4.g + 0.11*y4.b);\n"
725 " float py5 = 2.0 * (0.30*y5.r + 0.59*y5.g + 0.11*y5.b);\n"
726 " float py6 = 1.0 * (0.30*y6.r + 0.59*y6.g + 0.11*y6.b);\n"
727 " sobel = vec3(0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6));\n"
728 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
729 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
730 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
731 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
732 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
733 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
734 " //gl_FragColor = mix(gl_FragColor, vec4(vec3(sobel), 1), UseSobel);\n"
735 " gl_FragColor.rgb = gl_FragColor.rgb * UserVec2.y + vec3(sobel)*UserVec2.x;\n"
738 "#ifdef USESATURATION\n"
739 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
740 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
741 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
742 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
745 "#ifdef USEGAMMARAMPS\n"
746 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
747 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
748 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
752 "#else // !MODE_POSTPROCESS\n"
757 "#ifdef MODE_GENERIC\n"
758 "#ifdef USEDIFFUSE\n"
759 "varying vec2 TexCoord1;\n"
761 "#ifdef USESPECULAR\n"
762 "varying vec2 TexCoord2;\n"
764 "#ifdef VERTEX_SHADER\n"
767 " gl_FrontColor = gl_Color;\n"
768 "#ifdef USEDIFFUSE\n"
769 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
771 "#ifdef USESPECULAR\n"
772 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
774 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
778 "#ifdef FRAGMENT_SHADER\n"
779 "#ifdef USEDIFFUSE\n"
780 "uniform sampler2D Texture_First;\n"
782 "#ifdef USESPECULAR\n"
783 "uniform sampler2D Texture_Second;\n"
788 " gl_FragColor = gl_Color;\n"
789 "#ifdef USEDIFFUSE\n"
790 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
793 "#ifdef USESPECULAR\n"
794 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
795 "# ifdef USECOLORMAPPING\n"
796 " gl_FragColor *= tex2;\n"
799 " gl_FragColor += tex2;\n"
801 "# ifdef USEVERTEXTEXTUREBLEND\n"
802 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
807 "#else // !MODE_GENERIC\n"
812 "#ifdef MODE_BLOOMBLUR\n"
813 "varying TexCoord;\n"
814 "#ifdef VERTEX_SHADER\n"
817 " gl_FrontColor = gl_Color;\n"
818 " TexCoord = gl_MultiTexCoord0.xy;\n"
819 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
823 "#ifdef FRAGMENT_SHADER\n"
824 "uniform sampler2D Texture_First;\n"
825 "uniform vec4 BloomBlur_Parameters;\n"
830 " vec2 tc = TexCoord;\n"
831 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
832 " tc += BloomBlur_Parameters.xy;\n"
833 " for (i = 1;i < SAMPLES;i++)\n"
835 " color += texture2D(Texture_First, tc).rgb;\n"
836 " tc += BloomBlur_Parameters.xy;\n"
838 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
841 "#else // !MODE_BLOOMBLUR\n"
842 "#ifdef MODE_REFRACTION\n"
843 "varying vec2 TexCoord;\n"
844 "varying vec4 ModelViewProjectionPosition;\n"
845 "uniform mat4 TexMatrix;\n"
846 "#ifdef VERTEX_SHADER\n"
850 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
851 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
852 " ModelViewProjectionPosition = gl_Position;\n"
856 "#ifdef FRAGMENT_SHADER\n"
857 "uniform sampler2D Texture_Normal;\n"
858 "uniform sampler2D Texture_Refraction;\n"
859 "uniform sampler2D Texture_Reflection;\n"
861 "uniform vec4 DistortScaleRefractReflect;\n"
862 "uniform vec4 ScreenScaleRefractReflect;\n"
863 "uniform vec4 ScreenCenterRefractReflect;\n"
864 "uniform vec4 RefractColor;\n"
865 "uniform vec4 ReflectColor;\n"
866 "uniform float ReflectFactor;\n"
867 "uniform float ReflectOffset;\n"
871 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
872 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
873 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
874 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
875 " // FIXME temporary hack to detect the case that the reflection\n"
876 " // gets blackened at edges due to leaving the area that contains actual\n"
878 " // Remove this 'ack once we have a better way to stop this thing from\n"
880 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
881 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
882 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
883 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
884 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
885 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
888 "#else // !MODE_REFRACTION\n"
893 "#ifdef MODE_WATER\n"
894 "varying vec2 TexCoord;\n"
895 "varying vec3 EyeVector;\n"
896 "varying vec4 ModelViewProjectionPosition;\n"
897 "#ifdef VERTEX_SHADER\n"
898 "uniform vec3 EyePosition;\n"
899 "uniform mat4 TexMatrix;\n"
903 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
904 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
905 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
906 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
907 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
908 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
909 " ModelViewProjectionPosition = gl_Position;\n"
913 "#ifdef FRAGMENT_SHADER\n"
914 "uniform sampler2D Texture_Normal;\n"
915 "uniform sampler2D Texture_Refraction;\n"
916 "uniform sampler2D Texture_Reflection;\n"
918 "uniform vec4 DistortScaleRefractReflect;\n"
919 "uniform vec4 ScreenScaleRefractReflect;\n"
920 "uniform vec4 ScreenCenterRefractReflect;\n"
921 "uniform vec4 RefractColor;\n"
922 "uniform vec4 ReflectColor;\n"
923 "uniform float ReflectFactor;\n"
924 "uniform float ReflectOffset;\n"
928 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
929 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
930 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
931 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
932 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
933 " // FIXME temporary hack to detect the case that the reflection\n"
934 " // gets blackened at edges due to leaving the area that contains actual\n"
936 " // Remove this 'ack once we have a better way to stop this thing from\n"
938 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
939 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
940 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
941 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
942 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
943 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
944 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
945 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
946 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
947 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
948 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
949 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
952 "#else // !MODE_WATER\n"
957 "// common definitions between vertex shader and fragment shader:\n"
959 "varying vec2 TexCoord;\n"
960 "#ifdef USEVERTEXTEXTUREBLEND\n"
961 "varying vec2 TexCoord2;\n"
963 "#ifdef USELIGHTMAP\n"
964 "varying vec2 TexCoordLightmap;\n"
967 "#ifdef MODE_LIGHTSOURCE\n"
968 "varying vec3 CubeVector;\n"
971 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
972 "varying vec3 LightVector;\n"
975 "#ifdef USEEYEVECTOR\n"
976 "varying vec3 EyeVector;\n"
979 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
982 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
983 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
984 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
985 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
988 "#ifdef USEREFLECTION\n"
989 "varying vec4 ModelViewProjectionPosition;\n"
991 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
992 "uniform vec3 LightPosition;\n"
993 "varying vec4 ModelViewPosition;\n"
996 "#ifdef MODE_LIGHTSOURCE\n"
997 "uniform vec3 LightPosition;\n"
999 "uniform vec3 EyePosition;\n"
1000 "#ifdef MODE_LIGHTDIRECTION\n"
1001 "uniform vec3 LightDir;\n"
1003 "uniform vec4 FogPlane;\n"
1005 "#ifdef USESHADOWMAPORTHO\n"
1006 "varying vec3 ShadowMapTC;\n"
1013 "// 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"
1015 "// fragment shader specific:\n"
1016 "#ifdef FRAGMENT_SHADER\n"
1018 "uniform sampler2D Texture_Normal;\n"
1019 "uniform sampler2D Texture_Color;\n"
1020 "uniform sampler2D Texture_Gloss;\n"
1022 "uniform sampler2D Texture_Glow;\n"
1024 "#ifdef USEVERTEXTEXTUREBLEND\n"
1025 "uniform sampler2D Texture_SecondaryNormal;\n"
1026 "uniform sampler2D Texture_SecondaryColor;\n"
1027 "uniform sampler2D Texture_SecondaryGloss;\n"
1029 "uniform sampler2D Texture_SecondaryGlow;\n"
1032 "#ifdef USECOLORMAPPING\n"
1033 "uniform sampler2D Texture_Pants;\n"
1034 "uniform sampler2D Texture_Shirt;\n"
1037 "#ifdef USEFOGHEIGHTTEXTURE\n"
1038 "uniform sampler2D Texture_FogHeightTexture;\n"
1040 "uniform sampler2D Texture_FogMask;\n"
1042 "#ifdef USELIGHTMAP\n"
1043 "uniform sampler2D Texture_Lightmap;\n"
1045 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1046 "uniform sampler2D Texture_Deluxemap;\n"
1048 "#ifdef USEREFLECTION\n"
1049 "uniform sampler2D Texture_Reflection;\n"
1052 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1053 "uniform sampler2D Texture_ScreenDepth;\n"
1054 "uniform sampler2D Texture_ScreenNormalMap;\n"
1056 "#ifdef USEDEFERREDLIGHTMAP\n"
1057 "uniform sampler2D Texture_ScreenDiffuse;\n"
1058 "uniform sampler2D Texture_ScreenSpecular;\n"
1061 "uniform myhalf3 Color_Pants;\n"
1062 "uniform myhalf3 Color_Shirt;\n"
1063 "uniform myhalf3 FogColor;\n"
1066 "uniform float FogRangeRecip;\n"
1067 "uniform float FogPlaneViewDist;\n"
1068 "uniform float FogHeightFade;\n"
1069 "vec3 FogVertex(vec3 surfacecolor)\n"
1071 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1072 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1074 "#ifdef USEFOGHEIGHTTEXTURE\n"
1075 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1076 " fogfrac = fogheightpixel.a;\n"
1077 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1079 "# ifdef USEFOGOUTSIDE\n"
1080 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1082 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1084 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1089 "#ifdef USEOFFSETMAPPING\n"
1090 "uniform float OffsetMapping_Scale;\n"
1091 "vec2 OffsetMapping(vec2 TexCoord)\n"
1093 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1094 " // 14 sample relief mapping: linear search and then binary search\n"
1095 " // this basically steps forward a small amount repeatedly until it finds\n"
1096 " // itself inside solid, then jitters forward and back using decreasing\n"
1097 " // amounts to find the impact\n"
1098 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1099 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1100 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1101 " vec3 RT = vec3(TexCoord, 1);\n"
1102 " OffsetVector *= 0.1;\n"
1103 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1104 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1105 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1106 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1107 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1108 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1109 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1110 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1111 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1112 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1113 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1114 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1115 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1116 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1119 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1120 " // this basically moves forward the full distance, and then backs up based\n"
1121 " // on height of samples\n"
1122 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1123 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1124 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1125 " TexCoord += OffsetVector;\n"
1126 " OffsetVector *= 0.333;\n"
1127 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1128 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1129 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1130 " return TexCoord;\n"
1133 "#endif // USEOFFSETMAPPING\n"
1135 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1136 "uniform sampler2D Texture_Attenuation;\n"
1137 "uniform samplerCube Texture_Cube;\n"
1140 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1142 "#ifdef USESHADOWMAPRECT\n"
1143 "# ifdef USESHADOWSAMPLER\n"
1144 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1146 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1150 "#ifdef USESHADOWMAP2D\n"
1151 "# ifdef USESHADOWSAMPLER\n"
1152 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1154 "uniform sampler2D Texture_ShadowMap2D;\n"
1158 "#ifdef USESHADOWMAPVSDCT\n"
1159 "uniform samplerCube Texture_CubeProjection;\n"
1162 "#ifdef USESHADOWMAPCUBE\n"
1163 "# ifdef USESHADOWSAMPLER\n"
1164 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1166 "uniform samplerCube Texture_ShadowMapCube;\n"
1170 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1171 "uniform vec2 ShadowMap_TextureScale;\n"
1172 "uniform vec4 ShadowMap_Parameters;\n"
1175 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1176 "# ifdef USESHADOWMAPORTHO\n"
1177 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1179 "# ifdef USESHADOWMAPVSDCT\n"
1180 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1182 " vec3 adir = abs(dir);\n"
1183 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1184 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1185 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1188 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1190 " vec3 adir = abs(dir);\n"
1191 " float ma = adir.z;\n"
1192 " vec4 proj = vec4(dir, 2.5);\n"
1193 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1194 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1195 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1196 " return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1200 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1202 "#ifdef USESHADOWMAPCUBE\n"
1203 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1205 " vec3 adir = abs(dir);\n"
1206 " return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1210 "# ifdef USESHADOWMAPRECT\n"
1211 "float ShadowMapCompare(vec3 dir)\n"
1213 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1215 "# ifdef USESHADOWSAMPLER\n"
1217 "# ifdef USESHADOWMAPPCF\n"
1218 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1219 " 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"
1221 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1226 "# ifdef USESHADOWMAPPCF\n"
1227 "# if USESHADOWMAPPCF > 1\n"
1228 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1229 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1230 " 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"
1231 " 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"
1232 " 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"
1233 " 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"
1234 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1235 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1237 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1238 " vec2 offset = fract(shadowmaptc.xy);\n"
1239 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1240 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1241 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1242 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1243 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1246 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1250 "# ifdef USESHADOWMAPORTHO\n"
1251 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1258 "# ifdef USESHADOWMAP2D\n"
1259 "float ShadowMapCompare(vec3 dir)\n"
1261 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1264 "# ifdef USESHADOWSAMPLER\n"
1265 "# ifdef USESHADOWMAPPCF\n"
1266 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1267 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1268 " 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"
1270 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1273 "# ifdef USESHADOWMAPPCF\n"
1274 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1275 "# ifdef GL_ARB_texture_gather\n"
1276 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1278 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1280 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1281 "# if USESHADOWMAPPCF > 1\n"
1282 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1283 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1284 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1285 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1286 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1287 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1288 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1289 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1290 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1291 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1292 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1293 " locols.yz += group2.ab;\n"
1294 " hicols.yz += group8.rg;\n"
1295 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1296 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1297 " mix(locols, hicols, offset.y);\n"
1298 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1299 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1300 " f = dot(cols, vec4(1.0/25.0));\n"
1302 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1303 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1304 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1305 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1306 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1307 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1308 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1311 "# ifdef GL_EXT_gpu_shader4\n"
1312 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1314 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1316 "# if USESHADOWMAPPCF > 1\n"
1317 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1318 " center *= ShadowMap_TextureScale;\n"
1319 " 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"
1320 " 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"
1321 " 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"
1322 " 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"
1323 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1324 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1326 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1327 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1328 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1329 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1330 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1331 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1335 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1338 "# ifdef USESHADOWMAPORTHO\n"
1339 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1346 "# ifdef USESHADOWMAPCUBE\n"
1347 "float ShadowMapCompare(vec3 dir)\n"
1349 " // apply depth texture cubemap as light filter\n"
1350 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1352 "# ifdef USESHADOWSAMPLER\n"
1353 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1355 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1360 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1361 "#endif // FRAGMENT_SHADER\n"
1366 "#ifdef MODE_DEFERREDGEOMETRY\n"
1367 "#ifdef VERTEX_SHADER\n"
1368 "uniform mat4 TexMatrix;\n"
1369 "#ifdef USEVERTEXTEXTUREBLEND\n"
1370 "uniform mat4 BackgroundTexMatrix;\n"
1372 "uniform mat4 ModelViewMatrix;\n"
1375 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1376 "#ifdef USEVERTEXTEXTUREBLEND\n"
1377 " gl_FrontColor = gl_Color;\n"
1378 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1381 " // transform unnormalized eye direction into tangent space\n"
1382 "#ifdef USEOFFSETMAPPING\n"
1383 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1384 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1385 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1386 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1389 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1390 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1391 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1392 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1394 "#endif // VERTEX_SHADER\n"
1396 "#ifdef FRAGMENT_SHADER\n"
1399 "#ifdef USEOFFSETMAPPING\n"
1400 " // apply offsetmapping\n"
1401 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1402 "#define TexCoord TexCoordOffset\n"
1405 "#ifdef USEALPHAKILL\n"
1406 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1410 "#ifdef USEVERTEXTEXTUREBLEND\n"
1411 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1412 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1413 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1414 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1417 "#ifdef USEVERTEXTEXTUREBLEND\n"
1418 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1419 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1421 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1422 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1425 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1427 "#endif // FRAGMENT_SHADER\n"
1428 "#else // !MODE_DEFERREDGEOMETRY\n"
1433 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1434 "#ifdef VERTEX_SHADER\n"
1435 "uniform mat4 ModelViewMatrix;\n"
1438 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1439 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1441 "#endif // VERTEX_SHADER\n"
1443 "#ifdef FRAGMENT_SHADER\n"
1444 "uniform mat4 ViewToLight;\n"
1445 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1446 "uniform vec2 ScreenToDepth;\n"
1447 "uniform myhalf3 DeferredColor_Ambient;\n"
1448 "uniform myhalf3 DeferredColor_Diffuse;\n"
1449 "#ifdef USESPECULAR\n"
1450 "uniform myhalf3 DeferredColor_Specular;\n"
1451 "uniform myhalf SpecularPower;\n"
1453 "uniform myhalf2 PixelToScreenTexCoord;\n"
1456 " // calculate viewspace pixel position\n"
1457 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1459 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1460 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1461 " // decode viewspace pixel normal\n"
1462 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1463 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1464 " // surfacenormal = pixel normal in viewspace\n"
1465 " // LightVector = pixel to light in viewspace\n"
1466 " // CubeVector = position in lightspace\n"
1467 " // eyevector = pixel to view in viewspace\n"
1468 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1469 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1470 "#ifdef USEDIFFUSE\n"
1471 " // calculate diffuse shading\n"
1472 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1473 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1475 "#ifdef USESPECULAR\n"
1476 " // calculate directional shading\n"
1477 " vec3 eyevector = position * -1.0;\n"
1478 "# ifdef USEEXACTSPECULARMATH\n"
1479 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1481 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1482 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1486 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1487 " fade *= ShadowMapCompare(CubeVector);\n"
1490 "#ifdef USEDIFFUSE\n"
1491 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1493 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1495 "#ifdef USESPECULAR\n"
1496 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1498 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1501 "# ifdef USECUBEFILTER\n"
1502 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1503 " gl_FragData[0].rgb *= cubecolor;\n"
1504 " gl_FragData[1].rgb *= cubecolor;\n"
1507 "#endif // FRAGMENT_SHADER\n"
1508 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1513 "#ifdef VERTEX_SHADER\n"
1514 "uniform mat4 TexMatrix;\n"
1515 "#ifdef USEVERTEXTEXTUREBLEND\n"
1516 "uniform mat4 BackgroundTexMatrix;\n"
1518 "#ifdef MODE_LIGHTSOURCE\n"
1519 "uniform mat4 ModelToLight;\n"
1521 "#ifdef USESHADOWMAPORTHO\n"
1522 "uniform mat4 ShadowMapMatrix;\n"
1526 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1527 " gl_FrontColor = gl_Color;\n"
1529 " // copy the surface texcoord\n"
1530 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1531 "#ifdef USEVERTEXTEXTUREBLEND\n"
1532 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1534 "#ifdef USELIGHTMAP\n"
1535 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1538 "#ifdef MODE_LIGHTSOURCE\n"
1539 " // transform vertex position into light attenuation/cubemap space\n"
1540 " // (-1 to +1 across the light box)\n"
1541 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1543 "# ifdef USEDIFFUSE\n"
1544 " // transform unnormalized light direction into tangent space\n"
1545 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1546 " // normalize it per pixel)\n"
1547 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1548 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1549 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1550 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1554 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1555 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1556 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1557 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1560 " // transform unnormalized eye direction into tangent space\n"
1561 "#ifdef USEEYEVECTOR\n"
1562 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1563 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1564 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1565 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1569 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1570 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1573 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1574 " VectorS = gl_MultiTexCoord1.xyz;\n"
1575 " VectorT = gl_MultiTexCoord2.xyz;\n"
1576 " VectorR = gl_MultiTexCoord3.xyz;\n"
1579 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1580 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1582 "#ifdef USESHADOWMAPORTHO\n"
1583 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1586 "#ifdef USEREFLECTION\n"
1587 " ModelViewProjectionPosition = gl_Position;\n"
1590 "#endif // VERTEX_SHADER\n"
1595 "#ifdef FRAGMENT_SHADER\n"
1596 "#ifdef USEDEFERREDLIGHTMAP\n"
1597 "uniform myhalf2 PixelToScreenTexCoord;\n"
1598 "uniform myhalf3 DeferredMod_Diffuse;\n"
1599 "uniform myhalf3 DeferredMod_Specular;\n"
1601 "uniform myhalf3 Color_Ambient;\n"
1602 "uniform myhalf3 Color_Diffuse;\n"
1603 "uniform myhalf3 Color_Specular;\n"
1604 "uniform myhalf SpecularPower;\n"
1606 "uniform myhalf3 Color_Glow;\n"
1608 "uniform myhalf Alpha;\n"
1609 "#ifdef USEREFLECTION\n"
1610 "uniform vec4 DistortScaleRefractReflect;\n"
1611 "uniform vec4 ScreenScaleRefractReflect;\n"
1612 "uniform vec4 ScreenCenterRefractReflect;\n"
1613 "uniform myhalf4 ReflectColor;\n"
1615 "#ifdef USEREFLECTCUBE\n"
1616 "uniform mat4 ModelToReflectCube;\n"
1617 "uniform sampler2D Texture_ReflectMask;\n"
1618 "uniform samplerCube Texture_ReflectCube;\n"
1620 "#ifdef MODE_LIGHTDIRECTION\n"
1621 "uniform myhalf3 LightColor;\n"
1623 "#ifdef MODE_LIGHTSOURCE\n"
1624 "uniform myhalf3 LightColor;\n"
1628 "#ifdef USEOFFSETMAPPING\n"
1629 " // apply offsetmapping\n"
1630 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1631 "#define TexCoord TexCoordOffset\n"
1634 " // combine the diffuse textures (base, pants, shirt)\n"
1635 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1636 "#ifdef USEALPHAKILL\n"
1637 " if (color.a < 0.5)\n"
1640 " color.a *= Alpha;\n"
1641 "#ifdef USECOLORMAPPING\n"
1642 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1644 "#ifdef USEVERTEXTEXTUREBLEND\n"
1645 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1646 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1647 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1648 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1650 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1653 " // get the surface normal\n"
1654 "#ifdef USEVERTEXTEXTUREBLEND\n"
1655 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1657 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1660 " // get the material colors\n"
1661 " myhalf3 diffusetex = color.rgb;\n"
1662 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1663 "# ifdef USEVERTEXTEXTUREBLEND\n"
1664 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1666 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1670 "#ifdef USEREFLECTCUBE\n"
1671 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1672 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1673 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1674 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1680 "#ifdef MODE_LIGHTSOURCE\n"
1681 " // light source\n"
1682 "#ifdef USEDIFFUSE\n"
1683 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1684 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1685 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1686 "#ifdef USESPECULAR\n"
1687 "#ifdef USEEXACTSPECULARMATH\n"
1688 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1690 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1691 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1693 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1696 " color.rgb = diffusetex * Color_Ambient;\n"
1698 " color.rgb *= LightColor;\n"
1699 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1700 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1701 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1703 "# ifdef USECUBEFILTER\n"
1704 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1706 "#endif // MODE_LIGHTSOURCE\n"
1711 "#ifdef MODE_LIGHTDIRECTION\n"
1713 "#ifdef USEDIFFUSE\n"
1714 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1716 "#define lightcolor LightColor\n"
1717 "#endif // MODE_LIGHTDIRECTION\n"
1718 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1720 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1721 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1722 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1723 " // convert modelspace light vector to tangentspace\n"
1724 " myhalf3 lightnormal;\n"
1725 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1726 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1727 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1728 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1729 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1730 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1731 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1732 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1733 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1734 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1735 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1736 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1737 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1738 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1739 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1741 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1742 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1743 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1749 "#ifdef MODE_LIGHTMAP\n"
1750 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1751 "#endif // MODE_LIGHTMAP\n"
1752 "#ifdef MODE_VERTEXCOLOR\n"
1753 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1754 "#endif // MODE_VERTEXCOLOR\n"
1755 "#ifdef MODE_FLATCOLOR\n"
1756 " color.rgb = diffusetex * Color_Ambient;\n"
1757 "#endif // MODE_FLATCOLOR\n"
1763 "# ifdef USEDIFFUSE\n"
1764 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1765 "# ifdef USESPECULAR\n"
1766 "# ifdef USEEXACTSPECULARMATH\n"
1767 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1769 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1770 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1772 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1774 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1777 " color.rgb = diffusetex * Color_Ambient;\n"
1781 "#ifdef USESHADOWMAPORTHO\n"
1782 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1785 "#ifdef USEDEFERREDLIGHTMAP\n"
1786 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1787 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1788 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1792 "#ifdef USEVERTEXTEXTUREBLEND\n"
1793 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1795 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1800 " color.rgb = FogVertex(color.rgb);\n"
1803 " // 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"
1804 "#ifdef USEREFLECTION\n"
1805 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1806 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1807 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1808 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1809 " // FIXME temporary hack to detect the case that the reflection\n"
1810 " // gets blackened at edges due to leaving the area that contains actual\n"
1812 " // Remove this 'ack once we have a better way to stop this thing from\n"
1814 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1815 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1816 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1817 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1818 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1819 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1822 " gl_FragColor = vec4(color);\n"
1824 "#endif // FRAGMENT_SHADER\n"
1826 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1827 "#endif // !MODE_DEFERREDGEOMETRY\n"
1828 "#endif // !MODE_WATER\n"
1829 "#endif // !MODE_REFRACTION\n"
1830 "#endif // !MODE_BLOOMBLUR\n"
1831 "#endif // !MODE_GENERIC\n"
1832 "#endif // !MODE_POSTPROCESS\n"
1833 "#endif // !MODE_SHOWDEPTH\n"
1834 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1838 =========================================================================================================================================================
1842 =========================================================================================================================================================
1846 =========================================================================================================================================================
1850 =========================================================================================================================================================
1854 =========================================================================================================================================================
1858 =========================================================================================================================================================
1862 =========================================================================================================================================================
1865 const char *builtincgshaderstring =
1866 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1867 "// written by Forest 'LordHavoc' Hale\n"
1868 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1870 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1871 "#if defined(USEREFLECTION)\n"
1872 "#undef USESHADOWMAPORTHO\n"
1875 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1878 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1879 "#define USELIGHTMAP\n"
1881 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1882 "#define USEEYEVECTOR\n"
1885 "#ifdef FRAGMENT_SHADER\n"
1886 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1889 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1890 "#ifdef VERTEX_SHADER\n"
1893 "float4 gl_Vertex : POSITION,\n"
1894 "uniform float4x4 ModelViewProjectionMatrix,\n"
1895 "out float4 gl_Position : POSITION\n"
1898 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1901 "#else // !MODE_DEPTH_ORSHADOW\n"
1906 "#ifdef MODE_SHOWDEPTH\n"
1907 "#ifdef VERTEX_SHADER\n"
1910 "float4 gl_Vertex : POSITION,\n"
1911 "uniform float4x4 ModelViewProjectionMatrix,\n"
1912 "out float4 gl_Position : POSITION,\n"
1913 "out float4 gl_FrontColor : COLOR0\n"
1916 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1917 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1921 "#ifdef FRAGMENT_SHADER\n"
1924 "float4 gl_FrontColor : COLOR0,\n"
1925 "out float4 gl_FragColor : COLOR\n"
1928 " gl_FragColor = gl_FrontColor;\n"
1931 "#else // !MODE_SHOWDEPTH\n"
1936 "#ifdef MODE_POSTPROCESS\n"
1938 "#ifdef VERTEX_SHADER\n"
1941 "float4 gl_Vertex : POSITION,\n"
1942 "uniform float4x4 ModelViewProjectionMatrix,\n"
1943 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1944 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1945 "out float4 gl_Position : POSITION,\n"
1946 "out float2 TexCoord1 : TEXCOORD0,\n"
1947 "out float2 TexCoord2 : TEXCOORD1\n"
1950 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1951 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1953 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1958 "#ifdef FRAGMENT_SHADER\n"
1961 "float2 TexCoord1 : TEXCOORD0,\n"
1962 "float2 TexCoord2 : TEXCOORD1,\n"
1963 "uniform sampler2D Texture_First,\n"
1965 "uniform sampler2D Texture_Second,\n"
1967 "#ifdef USEGAMMARAMPS\n"
1968 "uniform sampler2D Texture_GammaRamps,\n"
1970 "#ifdef USESATURATION\n"
1971 "uniform float Saturation,\n"
1973 "#ifdef USEVIEWTINT\n"
1974 "uniform float4 ViewTintColor,\n"
1976 "uniform float4 UserVec1,\n"
1977 "uniform float4 UserVec2,\n"
1978 "uniform float4 UserVec3,\n"
1979 "uniform float4 UserVec4,\n"
1980 "uniform float ClientTime,\n"
1981 "uniform float2 PixelSize,\n"
1982 "out float4 gl_FragColor : COLOR\n"
1985 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1987 " gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1989 "#ifdef USEVIEWTINT\n"
1990 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1993 "#ifdef USEPOSTPROCESSING\n"
1994 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1995 "// 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"
1996 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1997 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1998 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1999 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2000 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2001 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
2004 "#ifdef USESATURATION\n"
2005 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2006 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2007 " //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2008 " gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
2011 "#ifdef USEGAMMARAMPS\n"
2012 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2013 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2014 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2018 "#else // !MODE_POSTPROCESS\n"
2023 "#ifdef MODE_GENERIC\n"
2024 "#ifdef VERTEX_SHADER\n"
2027 "float4 gl_Vertex : POSITION,\n"
2028 "uniform float4x4 ModelViewProjectionMatrix,\n"
2029 "float4 gl_Color : COLOR0,\n"
2030 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2031 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2032 "out float4 gl_Position : POSITION,\n"
2033 "out float4 gl_FrontColor : COLOR,\n"
2034 "out float2 TexCoord1 : TEXCOORD0,\n"
2035 "out float2 TexCoord2 : TEXCOORD1\n"
2038 " gl_FrontColor = gl_Color;\n"
2039 "#ifdef USEDIFFUSE\n"
2040 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2042 "#ifdef USESPECULAR\n"
2043 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2045 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2049 "#ifdef FRAGMENT_SHADER\n"
2053 "float4 gl_FrontColor : COLOR,\n"
2054 "float2 TexCoord1 : TEXCOORD0,\n"
2055 "float2 TexCoord2 : TEXCOORD1,\n"
2056 "#ifdef USEDIFFUSE\n"
2057 "uniform sampler2D Texture_First,\n"
2059 "#ifdef USESPECULAR\n"
2060 "uniform sampler2D Texture_Second,\n"
2062 "out float4 gl_FragColor : COLOR\n"
2065 " gl_FragColor = gl_FrontColor;\n"
2066 "#ifdef USEDIFFUSE\n"
2067 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2070 "#ifdef USESPECULAR\n"
2071 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2072 "# ifdef USECOLORMAPPING\n"
2073 " gl_FragColor *= tex2;\n"
2076 " gl_FragColor += tex2;\n"
2078 "# ifdef USEVERTEXTEXTUREBLEND\n"
2079 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2084 "#else // !MODE_GENERIC\n"
2089 "#ifdef MODE_BLOOMBLUR\n"
2090 "#ifdef VERTEX_SHADER\n"
2093 "float4 gl_Vertex : POSITION,\n"
2094 "uniform float4x4 ModelViewProjectionMatrix,\n"
2095 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2096 "out float4 gl_Position : POSITION,\n"
2097 "out float2 TexCoord : TEXCOORD0\n"
2100 " TexCoord = gl_MultiTexCoord0.xy;\n"
2101 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2105 "#ifdef FRAGMENT_SHADER\n"
2109 "float2 TexCoord : TEXCOORD0,\n"
2110 "uniform sampler2D Texture_First,\n"
2111 "uniform float4 BloomBlur_Parameters,\n"
2112 "out float4 gl_FragColor : COLOR\n"
2116 " float2 tc = TexCoord;\n"
2117 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2118 " tc += BloomBlur_Parameters.xy;\n"
2119 " for (i = 1;i < SAMPLES;i++)\n"
2121 " color += tex2D(Texture_First, tc).rgb;\n"
2122 " tc += BloomBlur_Parameters.xy;\n"
2124 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2127 "#else // !MODE_BLOOMBLUR\n"
2128 "#ifdef MODE_REFRACTION\n"
2129 "#ifdef VERTEX_SHADER\n"
2132 "float4 gl_Vertex : POSITION,\n"
2133 "uniform float4x4 ModelViewProjectionMatrix,\n"
2134 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2135 "uniform float4x4 TexMatrix,\n"
2136 "uniform float3 EyePosition,\n"
2137 "out float4 gl_Position : POSITION,\n"
2138 "out float2 TexCoord : TEXCOORD0,\n"
2139 "out float3 EyeVector : TEXCOORD1,\n"
2140 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2143 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2144 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2145 " ModelViewProjectionPosition = gl_Position;\n"
2149 "#ifdef FRAGMENT_SHADER\n"
2152 "float2 TexCoord : TEXCOORD0,\n"
2153 "float3 EyeVector : TEXCOORD1,\n"
2154 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2155 "uniform sampler2D Texture_Normal,\n"
2156 "uniform sampler2D Texture_Refraction,\n"
2157 "uniform sampler2D Texture_Reflection,\n"
2158 "uniform float4 DistortScaleRefractReflect,\n"
2159 "uniform float4 ScreenScaleRefractReflect,\n"
2160 "uniform float4 ScreenCenterRefractReflect,\n"
2161 "uniform float4 RefractColor,\n"
2162 "out float4 gl_FragColor : COLOR\n"
2165 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2166 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2167 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2168 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2169 " // FIXME temporary hack to detect the case that the reflection\n"
2170 " // gets blackened at edges due to leaving the area that contains actual\n"
2172 " // Remove this 'ack once we have a better way to stop this thing from\n"
2174 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2175 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2176 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2177 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2178 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2179 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2182 "#else // !MODE_REFRACTION\n"
2187 "#ifdef MODE_WATER\n"
2188 "#ifdef VERTEX_SHADER\n"
2192 "float4 gl_Vertex : POSITION,\n"
2193 "uniform float4x4 ModelViewProjectionMatrix,\n"
2194 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2195 "uniform float4x4 TexMatrix,\n"
2196 "uniform float3 EyePosition,\n"
2197 "out float4 gl_Position : POSITION,\n"
2198 "out float2 TexCoord : TEXCOORD0,\n"
2199 "out float3 EyeVector : TEXCOORD1,\n"
2200 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2203 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2204 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2205 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2206 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2207 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2208 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2209 " ModelViewProjectionPosition = gl_Position;\n"
2213 "#ifdef FRAGMENT_SHADER\n"
2216 "float2 TexCoord : TEXCOORD0,\n"
2217 "float3 EyeVector : TEXCOORD1,\n"
2218 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2219 "uniform sampler2D Texture_Normal,\n"
2220 "uniform sampler2D Texture_Refraction,\n"
2221 "uniform sampler2D Texture_Reflection,\n"
2222 "uniform float4 DistortScaleRefractReflect,\n"
2223 "uniform float4 ScreenScaleRefractReflect,\n"
2224 "uniform float4 ScreenCenterRefractReflect,\n"
2225 "uniform float4 RefractColor,\n"
2226 "uniform float4 ReflectColor,\n"
2227 "uniform float ReflectFactor,\n"
2228 "uniform float ReflectOffset,\n"
2229 "out float4 gl_FragColor : COLOR\n"
2232 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2233 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2234 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2235 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2236 " // FIXME temporary hack to detect the case that the reflection\n"
2237 " // gets blackened at edges due to leaving the area that contains actual\n"
2239 " // Remove this 'ack once we have a better way to stop this thing from\n"
2241 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2242 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2243 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2244 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2245 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2246 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2247 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2248 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2249 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2250 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2251 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2252 " gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2255 "#else // !MODE_WATER\n"
2260 "// 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"
2262 "// fragment shader specific:\n"
2263 "#ifdef FRAGMENT_SHADER\n"
2266 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask, sampler2D Texture_FogHeightTexture)\n"
2269 "#ifdef USEFOGHEIGHTTEXTURE\n"
2270 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2271 " fogfrac = fogheightpixel.a;\n"
2272 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2274 "# ifdef USEFOGOUTSIDE\n"
2275 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2277 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2279 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2284 "#ifdef USEOFFSETMAPPING\n"
2285 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2287 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2288 " // 14 sample relief mapping: linear search and then binary search\n"
2289 " // this basically steps forward a small amount repeatedly until it finds\n"
2290 " // itself inside solid, then jitters forward and back using decreasing\n"
2291 " // amounts to find the impact\n"
2292 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2293 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2294 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2295 " float3 RT = float3(TexCoord, 1);\n"
2296 " OffsetVector *= 0.1;\n"
2297 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2298 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2299 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2300 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2301 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2302 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2303 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2304 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2305 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2306 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2307 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2308 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2309 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2310 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2313 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2314 " // this basically moves forward the full distance, and then backs up based\n"
2315 " // on height of samples\n"
2316 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2317 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2318 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2319 " TexCoord += OffsetVector;\n"
2320 " OffsetVector *= 0.333;\n"
2321 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2322 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2323 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2324 " return TexCoord;\n"
2327 "#endif // USEOFFSETMAPPING\n"
2329 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2330 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2331 "# ifdef USESHADOWMAPORTHO\n"
2332 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2334 "# ifdef USESHADOWMAPVSDCT\n"
2335 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2337 " float3 adir = abs(dir);\n"
2338 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2339 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2340 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2343 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2345 " float3 adir = abs(dir);\n"
2346 " float ma = adir.z;\n"
2347 " float4 proj = float4(dir, 2.5);\n"
2348 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2349 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2350 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2351 " return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2355 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2357 "#ifdef USESHADOWMAPCUBE\n"
2358 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2360 " float3 adir = abs(dir);\n"
2361 " return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2365 "# ifdef USESHADOWMAPRECT\n"
2366 "#ifdef USESHADOWMAPVSDCT\n"
2367 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2369 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2372 "#ifdef USESHADOWMAPVSDCT\n"
2373 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2375 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2378 "# ifdef USESHADOWSAMPLER\n"
2380 "# ifdef USESHADOWMAPPCF\n"
2381 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2382 " 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"
2384 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2389 "# ifdef USESHADOWMAPPCF\n"
2390 "# if USESHADOWMAPPCF > 1\n"
2391 "# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2392 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2393 " 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"
2394 " 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"
2395 " 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"
2396 " 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"
2397 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2398 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2400 "# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2401 " float2 offset = frac(shadowmaptc.xy);\n"
2402 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2403 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2404 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2405 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2406 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2409 " f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2413 "# ifdef USESHADOWMAPORTHO\n"
2414 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2421 "# ifdef USESHADOWMAP2D\n"
2422 "#ifdef USESHADOWMAPVSDCT\n"
2423 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2425 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2428 "#ifdef USESHADOWMAPVSDCT\n"
2429 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2431 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2435 "# ifdef USESHADOWSAMPLER\n"
2436 "# ifdef USESHADOWMAPPCF\n"
2437 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
2438 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2439 " 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"
2441 " f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2444 "# ifdef USESHADOWMAPPCF\n"
2445 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2446 "# ifdef GL_ARB_texture_gather\n"
2447 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2449 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2451 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2452 " center *= ShadowMap_TextureScale;\n"
2453 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2454 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2455 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2456 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2457 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2458 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2459 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2461 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale) \n"
2462 "# if USESHADOWMAPPCF > 1\n"
2463 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2464 " center *= ShadowMap_TextureScale;\n"
2465 " 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"
2466 " 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"
2467 " 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"
2468 " 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"
2469 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2470 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2472 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2473 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2474 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2475 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2476 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2477 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2481 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2484 "# ifdef USESHADOWMAPORTHO\n"
2485 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2492 "# ifdef USESHADOWMAPCUBE\n"
2493 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2495 " // apply depth texture cubemap as light filter\n"
2496 " float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2498 "# ifdef USESHADOWSAMPLER\n"
2499 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2501 " f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2506 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2507 "#endif // FRAGMENT_SHADER\n"
2512 "#ifdef MODE_DEFERREDGEOMETRY\n"
2513 "#ifdef VERTEX_SHADER\n"
2516 "float4 gl_Vertex : POSITION,\n"
2517 "uniform float4x4 ModelViewProjectionMatrix,\n"
2518 "#ifdef USEVERTEXTEXTUREBLEND\n"
2519 "float4 gl_Color : COLOR0,\n"
2521 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2522 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2523 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2524 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2525 "uniform float4x4 TexMatrix,\n"
2526 "#ifdef USEVERTEXTEXTUREBLEND\n"
2527 "uniform float4x4 BackgroundTexMatrix,\n"
2529 "uniform float4x4 ModelViewMatrix,\n"
2530 "#ifdef USEOFFSETMAPPING\n"
2531 "uniform float3 EyePosition,\n"
2533 "out float4 gl_Position : POSITION,\n"
2534 "out float4 gl_FrontColor : COLOR,\n"
2535 "out float4 TexCoordBoth : TEXCOORD0,\n"
2536 "#ifdef USEOFFSETMAPPING\n"
2537 "out float3 EyeVector : TEXCOORD2,\n"
2539 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2540 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2541 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2544 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2545 "#ifdef USEVERTEXTEXTUREBLEND\n"
2546 " gl_FrontColor = gl_Color;\n"
2547 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2550 " // transform unnormalized eye direction into tangent space\n"
2551 "#ifdef USEOFFSETMAPPING\n"
2552 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2553 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2554 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2555 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2558 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2559 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2560 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2561 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2563 "#endif // VERTEX_SHADER\n"
2565 "#ifdef FRAGMENT_SHADER\n"
2568 "float4 TexCoordBoth : TEXCOORD0,\n"
2569 "float3 EyeVector : TEXCOORD2,\n"
2570 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2571 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2572 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2573 "uniform sampler2D Texture_Normal,\n"
2574 "#ifdef USEALPHAKILL\n"
2575 "uniform sampler2D Texture_Color,\n"
2577 "uniform sampler2D Texture_Gloss,\n"
2578 "#ifdef USEVERTEXTEXTUREBLEND\n"
2579 "uniform sampler2D Texture_SecondaryNormal,\n"
2580 "uniform sampler2D Texture_SecondaryGloss,\n"
2582 "#ifdef USEOFFSETMAPPING\n"
2583 "uniform float OffsetMapping_Scale,\n"
2585 "uniform half SpecularPower,\n"
2586 "out float4 gl_FragColor : COLOR\n"
2589 " float2 TexCoord = TexCoordBoth.xy;\n"
2590 "#ifdef USEOFFSETMAPPING\n"
2591 " // apply offsetmapping\n"
2592 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2593 "#define TexCoord TexCoordOffset\n"
2596 "#ifdef USEALPHAKILL\n"
2597 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2601 "#ifdef USEVERTEXTEXTUREBLEND\n"
2602 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2603 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2604 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2605 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2608 "#ifdef USEVERTEXTEXTUREBLEND\n"
2609 " float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2610 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2612 " float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2613 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2616 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2618 "#endif // FRAGMENT_SHADER\n"
2619 "#else // !MODE_DEFERREDGEOMETRY\n"
2624 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2625 "#ifdef VERTEX_SHADER\n"
2628 "float4 gl_Vertex : POSITION,\n"
2629 "uniform float4x4 ModelViewProjectionMatrix,\n"
2630 "uniform float4x4 ModelViewMatrix,\n"
2631 "out float4 gl_Position : POSITION,\n"
2632 "out float4 ModelViewPosition : TEXCOORD0\n"
2635 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2636 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2638 "#endif // VERTEX_SHADER\n"
2640 "#ifdef FRAGMENT_SHADER\n"
2643 "float2 Pixel : WPOS,\n"
2644 "float4 ModelViewPosition : TEXCOORD0,\n"
2645 "uniform float4x4 ViewToLight,\n"
2646 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2647 "uniform float3 LightPosition,\n"
2648 "uniform half2 PixelToScreenTexCoord,\n"
2649 "uniform half3 DeferredColor_Ambient,\n"
2650 "uniform half3 DeferredColor_Diffuse,\n"
2651 "#ifdef USESPECULAR\n"
2652 "uniform half3 DeferredColor_Specular,\n"
2653 "uniform half SpecularPower,\n"
2655 "uniform sampler2D Texture_Attenuation,\n"
2656 "uniform sampler2D Texture_ScreenDepth,\n"
2657 "uniform sampler2D Texture_ScreenNormalMap,\n"
2659 "#ifdef USECUBEFILTER\n"
2660 "uniform samplerCUBE Texture_Cube,\n"
2663 "#ifdef USESHADOWMAPRECT\n"
2664 "# ifdef USESHADOWSAMPLER\n"
2665 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2667 "uniform samplerRECT Texture_ShadowMapRect,\n"
2671 "#ifdef USESHADOWMAP2D\n"
2672 "# ifdef USESHADOWSAMPLER\n"
2673 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2675 "uniform sampler2D Texture_ShadowMap2D,\n"
2679 "#ifdef USESHADOWMAPVSDCT\n"
2680 "uniform samplerCUBE Texture_CubeProjection,\n"
2683 "#ifdef USESHADOWMAPCUBE\n"
2684 "# ifdef USESHADOWSAMPLER\n"
2685 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2687 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2691 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2692 "uniform float2 ShadowMap_TextureScale,\n"
2693 "uniform float4 ShadowMap_Parameters,\n"
2696 "out float4 gl_FragData0 : COLOR0,\n"
2697 "out float4 gl_FragData1 : COLOR1\n"
2700 " // calculate viewspace pixel position\n"
2701 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2702 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2703 " float3 position;\n"
2704 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2705 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2706 " // decode viewspace pixel normal\n"
2707 " half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2708 " half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2709 " // surfacenormal = pixel normal in viewspace\n"
2710 " // LightVector = pixel to light in viewspace\n"
2711 " // CubeVector = position in lightspace\n"
2712 " // eyevector = pixel to view in viewspace\n"
2713 " float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2714 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2715 "#ifdef USEDIFFUSE\n"
2716 " // calculate diffuse shading\n"
2717 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2718 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2720 "#ifdef USESPECULAR\n"
2721 " // calculate directional shading\n"
2722 " float3 eyevector = position * -1.0;\n"
2723 "# ifdef USEEXACTSPECULARMATH\n"
2724 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2726 " half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2727 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2731 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2732 " fade *= ShadowMapCompare(CubeVector,\n"
2733 "# if defined(USESHADOWMAP2D)\n"
2734 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2736 "# if defined(USESHADOWMAPRECT)\n"
2737 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2739 "# if defined(USESHADOWMAPCUBE)\n"
2740 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2743 "#ifdef USESHADOWMAPVSDCT\n"
2744 ", Texture_CubeProjection\n"
2749 "#ifdef USEDIFFUSE\n"
2750 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2752 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2754 "#ifdef USESPECULAR\n"
2755 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2757 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2760 "# ifdef USECUBEFILTER\n"
2761 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2762 " gl_FragData0.rgb *= cubecolor;\n"
2763 " gl_FragData1.rgb *= cubecolor;\n"
2766 "#endif // FRAGMENT_SHADER\n"
2767 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2772 "#ifdef VERTEX_SHADER\n"
2775 "float4 gl_Vertex : POSITION,\n"
2776 "uniform float4x4 ModelViewProjectionMatrix,\n"
2777 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2778 "float4 gl_Color : COLOR0,\n"
2780 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2781 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2782 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2783 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2784 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2786 "uniform float3 EyePosition,\n"
2787 "uniform float4x4 TexMatrix,\n"
2788 "#ifdef USEVERTEXTEXTUREBLEND\n"
2789 "uniform float4x4 BackgroundTexMatrix,\n"
2791 "#ifdef MODE_LIGHTSOURCE\n"
2792 "uniform float4x4 ModelToLight,\n"
2794 "#ifdef MODE_LIGHTSOURCE\n"
2795 "uniform float3 LightPosition,\n"
2797 "#ifdef MODE_LIGHTDIRECTION\n"
2798 "uniform float3 LightDir,\n"
2800 "uniform float4 FogPlane,\n"
2801 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2802 "uniform float3 LightPosition,\n"
2804 "#ifdef USESHADOWMAPORTHO\n"
2805 "uniform float4x4 ShadowMapMatrix,\n"
2808 "out float4 gl_FrontColor : COLOR,\n"
2809 "out float4 TexCoordBoth : TEXCOORD0,\n"
2810 "#ifdef USELIGHTMAP\n"
2811 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2813 "#ifdef USEEYEVECTOR\n"
2814 "out float3 EyeVector : TEXCOORD2,\n"
2816 "#ifdef USEREFLECTION\n"
2817 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2820 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2822 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2823 "out float3 LightVector : TEXCOORD1,\n"
2825 "#ifdef MODE_LIGHTSOURCE\n"
2826 "out float3 CubeVector : TEXCOORD3,\n"
2828 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2829 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2830 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2831 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2833 "#ifdef USESHADOWMAPORTHO\n"
2834 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2836 "out float4 gl_Position : POSITION\n"
2839 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2840 " gl_FrontColor = gl_Color;\n"
2842 " // copy the surface texcoord\n"
2843 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2844 "#ifdef USEVERTEXTEXTUREBLEND\n"
2845 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2847 "#ifdef USELIGHTMAP\n"
2848 " TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2851 "#ifdef MODE_LIGHTSOURCE\n"
2852 " // transform vertex position into light attenuation/cubemap space\n"
2853 " // (-1 to +1 across the light box)\n"
2854 " CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2856 "# ifdef USEDIFFUSE\n"
2857 " // transform unnormalized light direction into tangent space\n"
2858 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2859 " // normalize it per pixel)\n"
2860 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2861 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2862 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2863 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2867 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2868 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2869 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2870 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2873 " // transform unnormalized eye direction into tangent space\n"
2874 "#ifdef USEEYEVECTOR\n"
2875 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2876 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2877 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2878 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2882 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2883 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2886 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2887 " VectorS = gl_MultiTexCoord1.xyz;\n"
2888 " VectorT = gl_MultiTexCoord2.xyz;\n"
2889 " VectorR = gl_MultiTexCoord3.xyz;\n"
2892 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2893 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2895 "#ifdef USESHADOWMAPORTHO\n"
2896 " ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2899 "#ifdef USEREFLECTION\n"
2900 " ModelViewProjectionPosition = gl_Position;\n"
2903 "#endif // VERTEX_SHADER\n"
2908 "#ifdef FRAGMENT_SHADER\n"
2911 "#ifdef USEDEFERREDLIGHTMAP\n"
2912 "float2 Pixel : WPOS,\n"
2914 "float4 gl_FrontColor : COLOR,\n"
2915 "float4 TexCoordBoth : TEXCOORD0,\n"
2916 "#ifdef USELIGHTMAP\n"
2917 "float2 TexCoordLightmap : TEXCOORD1,\n"
2919 "#ifdef USEEYEVECTOR\n"
2920 "float3 EyeVector : TEXCOORD2,\n"
2922 "#ifdef USEREFLECTION\n"
2923 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2926 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2928 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2929 "float3 LightVector : TEXCOORD1,\n"
2931 "#ifdef MODE_LIGHTSOURCE\n"
2932 "float3 CubeVector : TEXCOORD3,\n"
2934 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2935 "float4 ModelViewPosition : TEXCOORD0,\n"
2937 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2938 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2939 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2940 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2942 "#ifdef USESHADOWMAPORTHO\n"
2943 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2946 "uniform sampler2D Texture_Normal,\n"
2947 "uniform sampler2D Texture_Color,\n"
2948 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2949 "uniform sampler2D Texture_Gloss,\n"
2952 "uniform sampler2D Texture_Glow,\n"
2954 "#ifdef USEVERTEXTEXTUREBLEND\n"
2955 "uniform sampler2D Texture_SecondaryNormal,\n"
2956 "uniform sampler2D Texture_SecondaryColor,\n"
2957 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2958 "uniform sampler2D Texture_SecondaryGloss,\n"
2961 "uniform sampler2D Texture_SecondaryGlow,\n"
2964 "#ifdef USECOLORMAPPING\n"
2965 "uniform sampler2D Texture_Pants,\n"
2966 "uniform sampler2D Texture_Shirt,\n"
2969 "uniform sampler2D Texture_FogHeightTexture,\n"
2970 "uniform sampler2D Texture_FogMask,\n"
2972 "#ifdef USELIGHTMAP\n"
2973 "uniform sampler2D Texture_Lightmap,\n"
2975 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2976 "uniform sampler2D Texture_Deluxemap,\n"
2978 "#ifdef USEREFLECTION\n"
2979 "uniform sampler2D Texture_Reflection,\n"
2982 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2983 "uniform sampler2D Texture_ScreenDepth,\n"
2984 "uniform sampler2D Texture_ScreenNormalMap,\n"
2986 "#ifdef USEDEFERREDLIGHTMAP\n"
2987 "uniform sampler2D Texture_ScreenDiffuse,\n"
2988 "uniform sampler2D Texture_ScreenSpecular,\n"
2991 "#ifdef USECOLORMAPPING\n"
2992 "uniform half3 Color_Pants,\n"
2993 "uniform half3 Color_Shirt,\n"
2996 "uniform float3 FogColor,\n"
2997 "uniform float FogRangeRecip,\n"
2998 "uniform float FogPlaneViewDist,\n"
2999 "uniform float FogHeightFade,\n"
3002 "#ifdef USEOFFSETMAPPING\n"
3003 "uniform float OffsetMapping_Scale,\n"
3006 "#ifdef USEDEFERREDLIGHTMAP\n"
3007 "uniform half2 PixelToScreenTexCoord,\n"
3008 "uniform half3 DeferredMod_Diffuse,\n"
3009 "uniform half3 DeferredMod_Specular,\n"
3011 "uniform half3 Color_Ambient,\n"
3012 "uniform half3 Color_Diffuse,\n"
3013 "uniform half3 Color_Specular,\n"
3014 "uniform half SpecularPower,\n"
3016 "uniform half3 Color_Glow,\n"
3018 "uniform half Alpha,\n"
3019 "#ifdef USEREFLECTION\n"
3020 "uniform float4 DistortScaleRefractReflect,\n"
3021 "uniform float4 ScreenScaleRefractReflect,\n"
3022 "uniform float4 ScreenCenterRefractReflect,\n"
3023 "uniform half4 ReflectColor,\n"
3025 "#ifdef USEREFLECTCUBE\n"
3026 "uniform float4x4 ModelToReflectCube,\n"
3027 "uniform sampler2D Texture_ReflectMask,\n"
3028 "uniform samplerCUBE Texture_ReflectCube,\n"
3030 "#ifdef MODE_LIGHTDIRECTION\n"
3031 "uniform half3 LightColor,\n"
3033 "#ifdef MODE_LIGHTSOURCE\n"
3034 "uniform half3 LightColor,\n"
3037 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3038 "uniform sampler2D Texture_Attenuation,\n"
3039 "uniform samplerCUBE Texture_Cube,\n"
3042 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3044 "#ifdef USESHADOWMAPRECT\n"
3045 "# ifdef USESHADOWSAMPLER\n"
3046 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
3048 "uniform samplerRECT Texture_ShadowMapRect,\n"
3052 "#ifdef USESHADOWMAP2D\n"
3053 "# ifdef USESHADOWSAMPLER\n"
3054 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
3056 "uniform sampler2D Texture_ShadowMap2D,\n"
3060 "#ifdef USESHADOWMAPVSDCT\n"
3061 "uniform samplerCUBE Texture_CubeProjection,\n"
3064 "#ifdef USESHADOWMAPCUBE\n"
3065 "# ifdef USESHADOWSAMPLER\n"
3066 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
3068 "uniform samplerCUBE Texture_ShadowMapCube,\n"
3072 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3073 "uniform float2 ShadowMap_TextureScale,\n"
3074 "uniform float4 ShadowMap_Parameters,\n"
3076 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3078 "out float4 gl_FragColor : COLOR\n"
3081 " float2 TexCoord = TexCoordBoth.xy;\n"
3082 "#ifdef USEVERTEXTEXTUREBLEND\n"
3083 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3085 "#ifdef USEOFFSETMAPPING\n"
3086 " // apply offsetmapping\n"
3087 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3088 "#define TexCoord TexCoordOffset\n"
3091 " // combine the diffuse textures (base, pants, shirt)\n"
3092 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3093 "#ifdef USEALPHAKILL\n"
3094 " if (color.a < 0.5)\n"
3097 " color.a *= Alpha;\n"
3098 "#ifdef USECOLORMAPPING\n"
3099 " color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
3101 "#ifdef USEVERTEXTEXTUREBLEND\n"
3102 " float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3103 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3104 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3105 " color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
3107 " //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
3110 " // get the surface normal\n"
3111 "#ifdef USEVERTEXTEXTUREBLEND\n"
3112 " half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3114 " half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
3117 " // get the material colors\n"
3118 " half3 diffusetex = color.rgb;\n"
3119 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3120 "# ifdef USEVERTEXTEXTUREBLEND\n"
3121 " half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
3123 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3127 "#ifdef USEREFLECTCUBE\n"
3128 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3129 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3130 " float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3131 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3137 "#ifdef MODE_LIGHTSOURCE\n"
3138 " // light source\n"
3139 "#ifdef USEDIFFUSE\n"
3140 " half3 lightnormal = half3(normalize(LightVector));\n"
3141 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3142 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3143 "#ifdef USESPECULAR\n"
3144 "#ifdef USEEXACTSPECULARMATH\n"
3145 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3147 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3148 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3150 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3153 " color.rgb = diffusetex * Color_Ambient;\n"
3155 " color.rgb *= LightColor;\n"
3156 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3157 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3158 " color.rgb *= ShadowMapCompare(CubeVector,\n"
3159 "# if defined(USESHADOWMAP2D)\n"
3160 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3162 "# if defined(USESHADOWMAPRECT)\n"
3163 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3165 "# if defined(USESHADOWMAPCUBE)\n"
3166 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3169 "#ifdef USESHADOWMAPVSDCT\n"
3170 ", Texture_CubeProjection\n"
3175 "# ifdef USECUBEFILTER\n"
3176 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3178 "#endif // MODE_LIGHTSOURCE\n"
3183 "#ifdef MODE_LIGHTDIRECTION\n"
3185 "#ifdef USEDIFFUSE\n"
3186 " half3 lightnormal = half3(normalize(LightVector));\n"
3188 "#define lightcolor LightColor\n"
3189 "#endif // MODE_LIGHTDIRECTION\n"
3190 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3192 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3193 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3194 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3195 " // convert modelspace light vector to tangentspace\n"
3196 " half3 lightnormal;\n"
3197 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3198 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3199 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3200 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3201 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3202 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3203 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3204 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3205 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3206 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3207 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3208 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3209 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3210 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3211 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3213 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3214 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3215 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3221 "#ifdef MODE_LIGHTMAP\n"
3222 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3223 "#endif // MODE_LIGHTMAP\n"
3224 "#ifdef MODE_VERTEXCOLOR\n"
3225 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3226 "#endif // MODE_VERTEXCOLOR\n"
3227 "#ifdef MODE_FLATCOLOR\n"
3228 " color.rgb = diffusetex * Color_Ambient;\n"
3229 "#endif // MODE_FLATCOLOR\n"
3235 "# ifdef USEDIFFUSE\n"
3236 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3237 "# ifdef USESPECULAR\n"
3238 "# ifdef USEEXACTSPECULARMATH\n"
3239 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3241 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3242 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3244 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3246 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3249 " color.rgb = diffusetex * Color_Ambient;\n"
3253 "#ifdef USESHADOWMAPORTHO\n"
3254 " color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3255 "# if defined(USESHADOWMAP2D)\n"
3256 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3258 "# if defined(USESHADOWMAPRECT)\n"
3259 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3264 "#ifdef USEDEFERREDLIGHTMAP\n"
3265 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3266 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3267 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3271 "#ifdef USEVERTEXTEXTUREBLEND\n"
3272 " color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3274 " color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3279 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3282 " // 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"
3283 "#ifdef USEREFLECTION\n"
3284 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3285 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3286 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3287 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3288 " // FIXME temporary hack to detect the case that the reflection\n"
3289 " // gets blackened at edges due to leaving the area that contains actual\n"
3291 " // Remove this 'ack once we have a better way to stop this thing from\n"
3293 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3294 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3295 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3296 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3297 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3298 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3301 " gl_FragColor = float4(color);\n"
3303 "#endif // FRAGMENT_SHADER\n"
3305 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3306 "#endif // !MODE_DEFERREDGEOMETRY\n"
3307 "#endif // !MODE_WATER\n"
3308 "#endif // !MODE_REFRACTION\n"
3309 "#endif // !MODE_BLOOMBLUR\n"
3310 "#endif // !MODE_GENERIC\n"
3311 "#endif // !MODE_POSTPROCESS\n"
3312 "#endif // !MODE_SHOWDEPTH\n"
3313 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3316 char *glslshaderstring = NULL;
3317 char *cgshaderstring = NULL;
3319 //=======================================================================================================================================================
3321 typedef struct shaderpermutationinfo_s
3323 const char *pretext;
3326 shaderpermutationinfo_t;
3328 typedef struct shadermodeinfo_s
3330 const char *vertexfilename;
3331 const char *geometryfilename;
3332 const char *fragmentfilename;
3333 const char *pretext;
3338 typedef enum shaderpermutation_e
3340 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3341 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3342 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3343 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3344 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3345 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3346 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3347 SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3348 SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3349 SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3350 SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3351 SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3352 SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3353 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3354 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3355 SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3356 SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3357 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3358 SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3359 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3360 SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3361 SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3362 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3363 SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3364 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3365 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3366 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3367 SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3368 SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3369 SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3370 SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3372 shaderpermutation_t;
3374 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3375 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3377 {"#define USEDIFFUSE\n", " diffuse"},
3378 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3379 {"#define USEVIEWTINT\n", " viewtint"},
3380 {"#define USECOLORMAPPING\n", " colormapping"},
3381 {"#define USESATURATION\n", " saturation"},
3382 {"#define USEFOGINSIDE\n", " foginside"},
3383 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3384 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3385 {"#define USEGAMMARAMPS\n", " gammaramps"},
3386 {"#define USECUBEFILTER\n", " cubefilter"},
3387 {"#define USEGLOW\n", " glow"},
3388 {"#define USEBLOOM\n", " bloom"},
3389 {"#define USESPECULAR\n", " specular"},
3390 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3391 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3392 {"#define USEREFLECTION\n", " reflection"},
3393 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3394 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3395 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3396 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3397 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3398 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3399 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3400 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3401 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3402 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3403 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3404 {"#define USEALPHAKILL\n", " alphakill"},
3405 {"#define USEREFLECTCUBE\n", " reflectcube"},
3408 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3409 typedef enum shadermode_e
3411 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3412 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3413 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3414 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3415 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3416 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3417 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3418 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3419 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3420 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3421 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3422 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3423 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3424 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3425 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3430 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3431 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3433 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3434 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3435 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3436 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3437 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3438 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3439 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3440 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3441 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3442 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3443 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3444 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3445 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3446 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3447 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3451 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3453 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3454 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3455 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3456 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3457 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3458 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3459 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3460 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3461 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3462 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3463 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3464 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3465 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3466 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3467 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3471 struct r_glsl_permutation_s;
3472 typedef struct r_glsl_permutation_s
3474 /// hash lookup data
3475 struct r_glsl_permutation_s *hashnext;
3477 unsigned int permutation;
3479 /// indicates if we have tried compiling this permutation already
3481 /// 0 if compilation failed
3483 /// locations of detected uniforms in program object, or -1 if not found
3484 int loc_Texture_First;
3485 int loc_Texture_Second;
3486 int loc_Texture_GammaRamps;
3487 int loc_Texture_Normal;
3488 int loc_Texture_Color;
3489 int loc_Texture_Gloss;
3490 int loc_Texture_Glow;
3491 int loc_Texture_SecondaryNormal;
3492 int loc_Texture_SecondaryColor;
3493 int loc_Texture_SecondaryGloss;
3494 int loc_Texture_SecondaryGlow;
3495 int loc_Texture_Pants;
3496 int loc_Texture_Shirt;
3497 int loc_Texture_FogHeightTexture;
3498 int loc_Texture_FogMask;
3499 int loc_Texture_Lightmap;
3500 int loc_Texture_Deluxemap;
3501 int loc_Texture_Attenuation;
3502 int loc_Texture_Cube;
3503 int loc_Texture_Refraction;
3504 int loc_Texture_Reflection;
3505 int loc_Texture_ShadowMapRect;
3506 int loc_Texture_ShadowMapCube;
3507 int loc_Texture_ShadowMap2D;
3508 int loc_Texture_CubeProjection;
3509 int loc_Texture_ScreenDepth;
3510 int loc_Texture_ScreenNormalMap;
3511 int loc_Texture_ScreenDiffuse;
3512 int loc_Texture_ScreenSpecular;
3513 int loc_Texture_ReflectMask;
3514 int loc_Texture_ReflectCube;
3516 int loc_BloomBlur_Parameters;
3518 int loc_Color_Ambient;
3519 int loc_Color_Diffuse;
3520 int loc_Color_Specular;
3522 int loc_Color_Pants;
3523 int loc_Color_Shirt;
3524 int loc_DeferredColor_Ambient;
3525 int loc_DeferredColor_Diffuse;
3526 int loc_DeferredColor_Specular;
3527 int loc_DeferredMod_Diffuse;
3528 int loc_DeferredMod_Specular;
3529 int loc_DistortScaleRefractReflect;
3530 int loc_EyePosition;
3532 int loc_FogHeightFade;
3534 int loc_FogPlaneViewDist;
3535 int loc_FogRangeRecip;
3538 int loc_LightPosition;
3539 int loc_OffsetMapping_Scale;
3541 int loc_ReflectColor;
3542 int loc_ReflectFactor;
3543 int loc_ReflectOffset;
3544 int loc_RefractColor;
3546 int loc_ScreenCenterRefractReflect;
3547 int loc_ScreenScaleRefractReflect;
3548 int loc_ScreenToDepth;
3549 int loc_ShadowMap_Parameters;
3550 int loc_ShadowMap_TextureScale;
3551 int loc_SpecularPower;
3556 // int loc_UseSobel;
3557 int loc_ViewTintColor;
3558 int loc_ViewToLight;
3559 int loc_ModelToLight;
3561 int loc_BackgroundTexMatrix;
3562 int loc_ModelViewProjectionMatrix;
3563 int loc_ModelViewMatrix;
3564 int loc_PixelToScreenTexCoord;
3565 int loc_ModelToReflectCube;
3566 int loc_ShadowMapMatrix;
3568 r_glsl_permutation_t;
3570 #define SHADERPERMUTATION_HASHSIZE 256
3572 /// information about each possible shader permutation
3573 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3574 /// currently selected permutation
3575 r_glsl_permutation_t *r_glsl_permutation;
3576 /// storage for permutations linked in the hash table
3577 memexpandablearray_t r_glsl_permutationarray;
3579 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3581 //unsigned int hashdepth = 0;
3582 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3583 r_glsl_permutation_t *p;
3584 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3586 if (p->mode == mode && p->permutation == permutation)
3588 //if (hashdepth > 10)
3589 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3594 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3596 p->permutation = permutation;
3597 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3598 r_glsl_permutationhash[mode][hashindex] = p;
3599 //if (hashdepth > 10)
3600 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3604 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3607 if (!filename || !filename[0])
3609 if (!strcmp(filename, "glsl/default.glsl"))
3611 if (!glslshaderstring)
3613 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3614 if (glslshaderstring)
3615 Con_DPrintf("Loading shaders from file %s...\n", filename);
3617 glslshaderstring = (char *)builtinshaderstring;
3619 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3620 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3621 return shaderstring;
3623 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3626 if (printfromdisknotice)
3627 Con_DPrintf("from disk %s... ", filename);
3628 return shaderstring;
3630 return shaderstring;
3633 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3636 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3637 int vertstrings_count = 0;
3638 int geomstrings_count = 0;
3639 int fragstrings_count = 0;
3640 char *vertexstring, *geometrystring, *fragmentstring;
3641 const char *vertstrings_list[32+3];
3642 const char *geomstrings_list[32+3];
3643 const char *fragstrings_list[32+3];
3644 char permutationname[256];
3651 permutationname[0] = 0;
3652 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3653 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3654 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3656 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3658 // the first pretext is which type of shader to compile as
3659 // (later these will all be bound together as a program object)
3660 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3661 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3662 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3664 // the second pretext is the mode (for example a light source)
3665 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3666 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3667 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3668 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3670 // now add all the permutation pretexts
3671 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3673 if (permutation & (1<<i))
3675 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3676 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3677 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3678 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3682 // keep line numbers correct
3683 vertstrings_list[vertstrings_count++] = "\n";
3684 geomstrings_list[geomstrings_count++] = "\n";
3685 fragstrings_list[fragstrings_count++] = "\n";
3689 // now append the shader text itself
3690 vertstrings_list[vertstrings_count++] = vertexstring;
3691 geomstrings_list[geomstrings_count++] = geometrystring;
3692 fragstrings_list[fragstrings_count++] = fragmentstring;
3694 // if any sources were NULL, clear the respective list
3696 vertstrings_count = 0;
3697 if (!geometrystring)
3698 geomstrings_count = 0;
3699 if (!fragmentstring)
3700 fragstrings_count = 0;
3702 // compile the shader program
3703 if (vertstrings_count + geomstrings_count + fragstrings_count)
3704 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3708 qglUseProgramObjectARB(p->program);CHECKGLERROR
3709 // look up all the uniform variable names we care about, so we don't
3710 // have to look them up every time we set them
3712 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3713 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3714 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3715 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3716 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3717 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3718 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3719 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3720 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3721 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3722 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3723 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3724 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3725 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3726 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3727 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3728 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3729 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3730 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3731 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3732 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3733 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3734 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3735 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3736 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3737 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3738 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3739 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3740 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3741 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3742 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3743 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3744 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3745 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3746 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3747 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3748 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3749 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3750 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3751 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3752 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3753 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3754 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3755 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3756 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3757 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3758 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3759 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3760 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3761 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3762 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3763 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3764 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3765 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3766 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3767 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3768 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3769 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3770 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3771 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3772 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3773 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3774 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3775 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3776 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3777 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3778 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3779 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3780 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3781 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3782 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3783 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3784 // p->loc_UseSobel = qglGetUniformLocationARB(p->program, "UseSobel");
3785 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3786 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3787 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3788 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3789 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3790 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3791 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3792 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3793 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3794 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3795 // initialize the samplers to refer to the texture units we use
3796 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3797 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3798 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3799 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3800 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3801 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3802 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3803 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3804 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3805 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3806 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3807 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3808 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3809 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3810 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3811 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3812 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3813 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3814 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3815 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3816 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3817 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3818 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
3819 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3820 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3821 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3822 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3823 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3824 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3825 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3826 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3828 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3831 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3835 Mem_Free(vertexstring);
3837 Mem_Free(geometrystring);
3839 Mem_Free(fragmentstring);
3842 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3844 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3845 if (r_glsl_permutation != perm)
3847 r_glsl_permutation = perm;
3848 if (!r_glsl_permutation->program)
3850 if (!r_glsl_permutation->compiled)
3851 R_GLSL_CompilePermutation(perm, mode, permutation);
3852 if (!r_glsl_permutation->program)
3854 // remove features until we find a valid permutation
3856 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3858 // reduce i more quickly whenever it would not remove any bits
3859 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3860 if (!(permutation & j))
3863 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3864 if (!r_glsl_permutation->compiled)
3865 R_GLSL_CompilePermutation(perm, mode, permutation);
3866 if (r_glsl_permutation->program)
3869 if (i >= SHADERPERMUTATION_COUNT)
3871 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3872 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3873 qglUseProgramObjectARB(0);CHECKGLERROR
3874 return; // no bit left to clear, entire mode is broken
3879 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3881 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3882 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3883 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3887 #include <Cg/cgGL.h>
3888 struct r_cg_permutation_s;
3889 typedef struct r_cg_permutation_s
3891 /// hash lookup data
3892 struct r_cg_permutation_s *hashnext;
3894 unsigned int permutation;
3896 /// indicates if we have tried compiling this permutation already
3898 /// 0 if compilation failed
3901 /// locations of detected parameters in programs, or NULL if not found
3902 CGparameter vp_EyePosition;
3903 CGparameter vp_FogPlane;
3904 CGparameter vp_LightDir;
3905 CGparameter vp_LightPosition;
3906 CGparameter vp_ModelToLight;
3907 CGparameter vp_TexMatrix;
3908 CGparameter vp_BackgroundTexMatrix;
3909 CGparameter vp_ModelViewProjectionMatrix;
3910 CGparameter vp_ModelViewMatrix;
3911 CGparameter vp_ShadowMapMatrix;
3913 CGparameter fp_Texture_First;
3914 CGparameter fp_Texture_Second;
3915 CGparameter fp_Texture_GammaRamps;
3916 CGparameter fp_Texture_Normal;
3917 CGparameter fp_Texture_Color;
3918 CGparameter fp_Texture_Gloss;
3919 CGparameter fp_Texture_Glow;
3920 CGparameter fp_Texture_SecondaryNormal;
3921 CGparameter fp_Texture_SecondaryColor;
3922 CGparameter fp_Texture_SecondaryGloss;
3923 CGparameter fp_Texture_SecondaryGlow;
3924 CGparameter fp_Texture_Pants;
3925 CGparameter fp_Texture_Shirt;
3926 CGparameter fp_Texture_FogHeightTexture;
3927 CGparameter fp_Texture_FogMask;
3928 CGparameter fp_Texture_Lightmap;
3929 CGparameter fp_Texture_Deluxemap;
3930 CGparameter fp_Texture_Attenuation;
3931 CGparameter fp_Texture_Cube;
3932 CGparameter fp_Texture_Refraction;
3933 CGparameter fp_Texture_Reflection;
3934 CGparameter fp_Texture_ShadowMapRect;
3935 CGparameter fp_Texture_ShadowMapCube;
3936 CGparameter fp_Texture_ShadowMap2D;
3937 CGparameter fp_Texture_CubeProjection;
3938 CGparameter fp_Texture_ScreenDepth;
3939 CGparameter fp_Texture_ScreenNormalMap;
3940 CGparameter fp_Texture_ScreenDiffuse;
3941 CGparameter fp_Texture_ScreenSpecular;
3942 CGparameter fp_Texture_ReflectMask;
3943 CGparameter fp_Texture_ReflectCube;
3944 CGparameter fp_Alpha;
3945 CGparameter fp_BloomBlur_Parameters;
3946 CGparameter fp_ClientTime;
3947 CGparameter fp_Color_Ambient;
3948 CGparameter fp_Color_Diffuse;
3949 CGparameter fp_Color_Specular;
3950 CGparameter fp_Color_Glow;
3951 CGparameter fp_Color_Pants;
3952 CGparameter fp_Color_Shirt;
3953 CGparameter fp_DeferredColor_Ambient;
3954 CGparameter fp_DeferredColor_Diffuse;
3955 CGparameter fp_DeferredColor_Specular;
3956 CGparameter fp_DeferredMod_Diffuse;
3957 CGparameter fp_DeferredMod_Specular;
3958 CGparameter fp_DistortScaleRefractReflect;
3959 CGparameter fp_EyePosition;
3960 CGparameter fp_FogColor;
3961 CGparameter fp_FogHeightFade;
3962 CGparameter fp_FogPlane;
3963 CGparameter fp_FogPlaneViewDist;
3964 CGparameter fp_FogRangeRecip;
3965 CGparameter fp_LightColor;
3966 CGparameter fp_LightDir;
3967 CGparameter fp_LightPosition;
3968 CGparameter fp_OffsetMapping_Scale;
3969 CGparameter fp_PixelSize;
3970 CGparameter fp_ReflectColor;
3971 CGparameter fp_ReflectFactor;
3972 CGparameter fp_ReflectOffset;
3973 CGparameter fp_RefractColor;
3974 CGparameter fp_Saturation;
3975 CGparameter fp_ScreenCenterRefractReflect;
3976 CGparameter fp_ScreenScaleRefractReflect;
3977 CGparameter fp_ScreenToDepth;
3978 CGparameter fp_ShadowMap_Parameters;
3979 CGparameter fp_ShadowMap_TextureScale;
3980 CGparameter fp_SpecularPower;
3981 CGparameter fp_UserVec1;
3982 CGparameter fp_UserVec2;
3983 CGparameter fp_UserVec3;
3984 CGparameter fp_UserVec4;
3985 CGparameter fp_ViewTintColor;
3986 CGparameter fp_ViewToLight;
3987 CGparameter fp_PixelToScreenTexCoord;
3988 CGparameter fp_ModelToReflectCube;
3992 /// information about each possible shader permutation
3993 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3994 /// currently selected permutation
3995 r_cg_permutation_t *r_cg_permutation;
3996 /// storage for permutations linked in the hash table
3997 memexpandablearray_t r_cg_permutationarray;
3999 #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));}}
4001 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4003 //unsigned int hashdepth = 0;
4004 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4005 r_cg_permutation_t *p;
4006 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4008 if (p->mode == mode && p->permutation == permutation)
4010 //if (hashdepth > 10)
4011 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4016 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4018 p->permutation = permutation;
4019 p->hashnext = r_cg_permutationhash[mode][hashindex];
4020 r_cg_permutationhash[mode][hashindex] = p;
4021 //if (hashdepth > 10)
4022 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4026 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4029 if (!filename || !filename[0])
4031 if (!strcmp(filename, "cg/default.cg"))
4033 if (!cgshaderstring)
4035 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4037 Con_DPrintf("Loading shaders from file %s...\n", filename);
4039 cgshaderstring = (char *)builtincgshaderstring;
4041 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4042 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4043 return shaderstring;
4045 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4048 if (printfromdisknotice)
4049 Con_DPrintf("from disk %s... ", filename);
4050 return shaderstring;
4052 return shaderstring;
4055 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4057 // TODO: load or create .fp and .vp shader files
4060 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4063 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4064 int vertstrings_count = 0, vertstring_length = 0;
4065 int geomstrings_count = 0, geomstring_length = 0;
4066 int fragstrings_count = 0, fragstring_length = 0;
4068 char *vertexstring, *geometrystring, *fragmentstring;
4069 char *vertstring, *geomstring, *fragstring;
4070 const char *vertstrings_list[32+3];
4071 const char *geomstrings_list[32+3];
4072 const char *fragstrings_list[32+3];
4073 char permutationname[256];
4074 char cachename[256];
4075 CGprofile vertexProfile;
4076 CGprofile fragmentProfile;
4084 permutationname[0] = 0;
4086 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4087 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4088 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4090 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4091 strlcat(cachename, "cg/", sizeof(cachename));
4093 // the first pretext is which type of shader to compile as
4094 // (later these will all be bound together as a program object)
4095 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4096 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4097 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4099 // the second pretext is the mode (for example a light source)
4100 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4101 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4102 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4103 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4104 strlcat(cachename, modeinfo->name, sizeof(cachename));
4106 // now add all the permutation pretexts
4107 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4109 if (permutation & (1<<i))
4111 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4112 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4113 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4114 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4115 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4119 // keep line numbers correct
4120 vertstrings_list[vertstrings_count++] = "\n";
4121 geomstrings_list[geomstrings_count++] = "\n";
4122 fragstrings_list[fragstrings_count++] = "\n";
4126 // replace spaces in the cachename with _ characters
4127 for (i = 0;cachename[i];i++)
4128 if (cachename[i] == ' ')
4131 // now append the shader text itself
4132 vertstrings_list[vertstrings_count++] = vertexstring;
4133 geomstrings_list[geomstrings_count++] = geometrystring;
4134 fragstrings_list[fragstrings_count++] = fragmentstring;
4136 // if any sources were NULL, clear the respective list
4138 vertstrings_count = 0;
4139 if (!geometrystring)
4140 geomstrings_count = 0;
4141 if (!fragmentstring)
4142 fragstrings_count = 0;
4144 vertstring_length = 0;
4145 for (i = 0;i < vertstrings_count;i++)
4146 vertstring_length += strlen(vertstrings_list[i]);
4147 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4148 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4149 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4151 geomstring_length = 0;
4152 for (i = 0;i < geomstrings_count;i++)
4153 geomstring_length += strlen(geomstrings_list[i]);
4154 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4155 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4156 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4158 fragstring_length = 0;
4159 for (i = 0;i < fragstrings_count;i++)
4160 fragstring_length += strlen(fragstrings_list[i]);
4161 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4162 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4163 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4167 //vertexProfile = CG_PROFILE_ARBVP1;
4168 //fragmentProfile = CG_PROFILE_ARBFP1;
4169 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4170 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4171 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4172 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4173 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4176 // try to load the cached shader, or generate one
4177 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4179 // if caching failed, do a dynamic compile for now
4181 if (vertstring[0] && !p->vprogram)
4182 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4184 if (fragstring[0] && !p->fprogram)
4185 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4188 // look up all the uniform variable names we care about, so we don't
4189 // have to look them up every time we set them
4193 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4194 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4195 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4196 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4197 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4198 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4199 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4200 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4201 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4202 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4203 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4204 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4210 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4211 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4212 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4213 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4214 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4215 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4216 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4217 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4218 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4219 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4220 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4221 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4222 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4223 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4224 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4225 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4226 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4227 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4228 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4229 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4230 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4231 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4232 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4233 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4234 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4235 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4236 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4237 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4238 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4239 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4240 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4241 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4242 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4243 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4244 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4245 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4246 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4247 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4248 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4249 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4250 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4251 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4252 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4253 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4254 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4255 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4256 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4257 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4258 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4259 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4260 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4261 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4262 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4263 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4264 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4265 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4266 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4267 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4268 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4269 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4270 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4271 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4272 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4273 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4274 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4275 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4276 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4277 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4278 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4279 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4280 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4281 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4282 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4283 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4284 // p->fp_UseSobel = cgGetNamedParameter(p->fprogram, "UseSobel");
4285 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4286 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4287 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4288 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4292 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4293 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4295 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4299 Mem_Free(vertstring);
4301 Mem_Free(geomstring);
4303 Mem_Free(fragstring);
4305 Mem_Free(vertexstring);
4307 Mem_Free(geometrystring);
4309 Mem_Free(fragmentstring);
4312 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4314 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4317 if (r_cg_permutation != perm)
4319 r_cg_permutation = perm;
4320 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4322 if (!r_cg_permutation->compiled)
4323 R_CG_CompilePermutation(perm, mode, permutation);
4324 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4326 // remove features until we find a valid permutation
4328 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4330 // reduce i more quickly whenever it would not remove any bits
4331 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4332 if (!(permutation & j))
4335 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4336 if (!r_cg_permutation->compiled)
4337 R_CG_CompilePermutation(perm, mode, permutation);
4338 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4341 if (i >= SHADERPERMUTATION_COUNT)
4343 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4344 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4345 return; // no bit left to clear, entire mode is broken
4351 if (r_cg_permutation->vprogram)
4353 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4354 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4355 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4359 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4360 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4362 if (r_cg_permutation->fprogram)
4364 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4365 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4366 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4370 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4371 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4375 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4376 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4377 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4380 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4382 cgGLSetTextureParameter(param, R_GetTexture(tex));
4383 cgGLEnableTextureParameter(param);
4387 void R_GLSL_Restart_f(void)
4389 unsigned int i, limit;
4390 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4391 Mem_Free(glslshaderstring);
4392 glslshaderstring = NULL;
4393 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4394 Mem_Free(cgshaderstring);
4395 cgshaderstring = NULL;
4396 switch(vid.renderpath)
4398 case RENDERPATH_GL20:
4400 r_glsl_permutation_t *p;
4401 r_glsl_permutation = NULL;
4402 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4403 for (i = 0;i < limit;i++)
4405 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4407 GL_Backend_FreeProgram(p->program);
4408 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4411 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4414 case RENDERPATH_CGGL:
4417 r_cg_permutation_t *p;
4418 r_cg_permutation = NULL;
4419 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4420 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4421 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4422 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4423 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4424 for (i = 0;i < limit;i++)
4426 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4429 cgDestroyProgram(p->vprogram);
4431 cgDestroyProgram(p->fprogram);
4432 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4435 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4439 case RENDERPATH_GL13:
4440 case RENDERPATH_GL11:
4445 void R_GLSL_DumpShader_f(void)
4450 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4453 FS_Print(file, "/* The engine may define the following macros:\n");
4454 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4455 for (i = 0;i < SHADERMODE_COUNT;i++)
4456 FS_Print(file, glslshadermodeinfo[i].pretext);
4457 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4458 FS_Print(file, shaderpermutationinfo[i].pretext);
4459 FS_Print(file, "*/\n");
4460 FS_Print(file, builtinshaderstring);
4462 Con_Printf("glsl/default.glsl written\n");
4465 Con_Printf("failed to write to glsl/default.glsl\n");
4468 file = FS_OpenRealFile("cg/default.cg", "w", false);
4471 FS_Print(file, "/* The engine may define the following macros:\n");
4472 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4473 for (i = 0;i < SHADERMODE_COUNT;i++)
4474 FS_Print(file, cgshadermodeinfo[i].pretext);
4475 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4476 FS_Print(file, shaderpermutationinfo[i].pretext);
4477 FS_Print(file, "*/\n");
4478 FS_Print(file, builtincgshaderstring);
4480 Con_Printf("cg/default.cg written\n");
4483 Con_Printf("failed to write to cg/default.cg\n");
4487 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4490 texturemode = GL_MODULATE;
4491 switch (vid.renderpath)
4493 case RENDERPATH_GL20:
4494 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))));
4495 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4496 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4498 case RENDERPATH_CGGL:
4501 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))));
4502 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4503 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4506 case RENDERPATH_GL13:
4507 R_Mesh_TexBind(0, first );
4508 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4509 R_Mesh_TexBind(1, second);
4511 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4513 case RENDERPATH_GL11:
4514 R_Mesh_TexBind(0, first );
4519 void R_SetupShader_DepthOrShadow(void)
4521 switch (vid.renderpath)
4523 case RENDERPATH_GL20:
4524 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4526 case RENDERPATH_CGGL:
4528 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4531 case RENDERPATH_GL13:
4532 R_Mesh_TexBind(0, 0);
4533 R_Mesh_TexBind(1, 0);
4535 case RENDERPATH_GL11:
4536 R_Mesh_TexBind(0, 0);
4541 void R_SetupShader_ShowDepth(void)
4543 switch (vid.renderpath)
4545 case RENDERPATH_GL20:
4546 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4548 case RENDERPATH_CGGL:
4550 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4553 case RENDERPATH_GL13:
4555 case RENDERPATH_GL11:
4560 extern qboolean r_shadow_usingdeferredprepass;
4561 extern cvar_t r_shadow_deferred_8bitrange;
4562 extern rtexture_t *r_shadow_attenuationgradienttexture;
4563 extern rtexture_t *r_shadow_attenuation2dtexture;
4564 extern rtexture_t *r_shadow_attenuation3dtexture;
4565 extern qboolean r_shadow_usingshadowmaprect;
4566 extern qboolean r_shadow_usingshadowmapcube;
4567 extern qboolean r_shadow_usingshadowmap2d;
4568 extern qboolean r_shadow_usingshadowmaportho;
4569 extern float r_shadow_shadowmap_texturescale[2];
4570 extern float r_shadow_shadowmap_parameters[4];
4571 extern qboolean r_shadow_shadowmapvsdct;
4572 extern qboolean r_shadow_shadowmapsampler;
4573 extern int r_shadow_shadowmappcf;
4574 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4575 extern rtexture_t *r_shadow_shadowmap2dtexture;
4576 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4577 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4578 extern matrix4x4_t r_shadow_shadowmapmatrix;
4579 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4580 extern int r_shadow_prepass_width;
4581 extern int r_shadow_prepass_height;
4582 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4583 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4584 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4585 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4586 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4588 // select a permutation of the lighting shader appropriate to this
4589 // combination of texture, entity, light source, and fogging, only use the
4590 // minimum features necessary to avoid wasting rendering time in the
4591 // fragment shader on features that are not being used
4592 unsigned int permutation = 0;
4593 unsigned int mode = 0;
4595 if (rsurfacepass == RSURFPASS_BACKGROUND)
4597 // distorted background
4598 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4599 mode = SHADERMODE_WATER;
4600 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4601 mode = SHADERMODE_REFRACTION;
4604 mode = SHADERMODE_GENERIC;
4605 permutation |= SHADERPERMUTATION_DIFFUSE;
4607 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4608 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4609 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4610 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4611 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4612 R_Mesh_ColorPointer(NULL, 0, 0);
4613 GL_AlphaTest(false);
4614 GL_BlendFunc(GL_ONE, GL_ZERO);
4616 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4618 if (r_glsl_offsetmapping.integer)
4620 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4621 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4622 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4623 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4624 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4626 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4627 if (r_glsl_offsetmapping_reliefmapping.integer)
4628 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4631 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4632 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4633 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4634 permutation |= SHADERPERMUTATION_ALPHAKILL;
4635 // normalmap (deferred prepass), may use alpha test on diffuse
4636 mode = SHADERMODE_DEFERREDGEOMETRY;
4637 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4638 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4639 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4640 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4641 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4642 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4643 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4644 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4645 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4647 R_Mesh_ColorPointer(NULL, 0, 0);
4648 GL_AlphaTest(false);
4649 GL_BlendFunc(GL_ONE, GL_ZERO);
4651 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4653 if (r_glsl_offsetmapping.integer)
4655 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4656 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4657 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4658 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4659 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4661 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4662 if (r_glsl_offsetmapping_reliefmapping.integer)
4663 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4666 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4667 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4669 mode = SHADERMODE_LIGHTSOURCE;
4670 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4671 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4672 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4673 permutation |= SHADERPERMUTATION_CUBEFILTER;
4674 if (diffusescale > 0)
4675 permutation |= SHADERPERMUTATION_DIFFUSE;
4676 if (specularscale > 0)
4678 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4679 if (r_shadow_glossexact.integer)
4680 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4682 if (r_refdef.fogenabled)
4683 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4684 if (rsurface.texture->colormapping)
4685 permutation |= SHADERPERMUTATION_COLORMAPPING;
4686 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4688 if (r_shadow_usingshadowmaprect)
4689 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4690 if (r_shadow_usingshadowmap2d)
4691 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4692 if (r_shadow_usingshadowmapcube)
4693 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4694 else if(r_shadow_shadowmapvsdct)
4695 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4697 if (r_shadow_shadowmapsampler)
4698 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4699 if (r_shadow_shadowmappcf > 1)
4700 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4701 else if (r_shadow_shadowmappcf)
4702 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4704 if (rsurface.texture->reflectmasktexture)
4705 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4706 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4707 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4709 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4710 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4711 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4715 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4716 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4717 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4719 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4720 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4721 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4723 R_Mesh_ColorPointer(NULL, 0, 0);
4724 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4725 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4727 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4729 if (r_glsl_offsetmapping.integer)
4731 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4732 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4733 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4734 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4735 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4737 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4738 if (r_glsl_offsetmapping_reliefmapping.integer)
4739 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4742 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4743 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4744 // unshaded geometry (fullbright or ambient model lighting)
4745 mode = SHADERMODE_FLATCOLOR;
4746 ambientscale = diffusescale = specularscale = 0;
4747 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4748 permutation |= SHADERPERMUTATION_GLOW;
4749 if (r_refdef.fogenabled)
4750 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4751 if (rsurface.texture->colormapping)
4752 permutation |= SHADERPERMUTATION_COLORMAPPING;
4753 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4755 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4756 if (r_shadow_usingshadowmaprect)
4757 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4758 if (r_shadow_usingshadowmap2d)
4759 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4761 if (r_shadow_shadowmapsampler)
4762 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4763 if (r_shadow_shadowmappcf > 1)
4764 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4765 else if (r_shadow_shadowmappcf)
4766 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4768 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4769 permutation |= SHADERPERMUTATION_REFLECTION;
4770 if (rsurface.texture->reflectmasktexture)
4771 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4772 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4773 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4775 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4776 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4777 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4781 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4782 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4783 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4785 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4786 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4787 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4789 R_Mesh_ColorPointer(NULL, 0, 0);
4790 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4791 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4793 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4795 if (r_glsl_offsetmapping.integer)
4797 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4798 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4799 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4800 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4801 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4803 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4804 if (r_glsl_offsetmapping_reliefmapping.integer)
4805 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4808 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4809 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4810 // directional model lighting
4811 mode = SHADERMODE_LIGHTDIRECTION;
4812 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4813 permutation |= SHADERPERMUTATION_GLOW;
4814 permutation |= SHADERPERMUTATION_DIFFUSE;
4815 if (specularscale > 0)
4817 permutation |= SHADERPERMUTATION_SPECULAR;
4818 if (r_shadow_glossexact.integer)
4819 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4821 if (r_refdef.fogenabled)
4822 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4823 if (rsurface.texture->colormapping)
4824 permutation |= SHADERPERMUTATION_COLORMAPPING;
4825 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4827 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4828 if (r_shadow_usingshadowmaprect)
4829 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4830 if (r_shadow_usingshadowmap2d)
4831 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4833 if (r_shadow_shadowmapsampler)
4834 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4835 if (r_shadow_shadowmappcf > 1)
4836 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4837 else if (r_shadow_shadowmappcf)
4838 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4840 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4841 permutation |= SHADERPERMUTATION_REFLECTION;
4842 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4843 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4844 if (rsurface.texture->reflectmasktexture)
4845 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4846 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4847 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4849 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4850 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4851 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4855 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4856 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4857 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4859 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4860 R_Mesh_ColorPointer(NULL, 0, 0);
4861 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4862 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4864 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4866 if (r_glsl_offsetmapping.integer)
4868 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4869 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4870 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4871 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4872 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4874 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4875 if (r_glsl_offsetmapping_reliefmapping.integer)
4876 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4879 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4880 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4881 // ambient model lighting
4882 mode = SHADERMODE_LIGHTDIRECTION;
4883 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4884 permutation |= SHADERPERMUTATION_GLOW;
4885 if (r_refdef.fogenabled)
4886 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4887 if (rsurface.texture->colormapping)
4888 permutation |= SHADERPERMUTATION_COLORMAPPING;
4889 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4891 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4892 if (r_shadow_usingshadowmaprect)
4893 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4894 if (r_shadow_usingshadowmap2d)
4895 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4897 if (r_shadow_shadowmapsampler)
4898 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4899 if (r_shadow_shadowmappcf > 1)
4900 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4901 else if (r_shadow_shadowmappcf)
4902 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4904 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4905 permutation |= SHADERPERMUTATION_REFLECTION;
4906 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4907 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4908 if (rsurface.texture->reflectmasktexture)
4909 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4910 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4911 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4913 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4914 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4915 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4919 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4920 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4921 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4923 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4924 R_Mesh_ColorPointer(NULL, 0, 0);
4925 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4926 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4930 if (r_glsl_offsetmapping.integer)
4932 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4933 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4934 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4935 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4936 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4938 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4939 if (r_glsl_offsetmapping_reliefmapping.integer)
4940 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4943 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4944 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4946 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4947 permutation |= SHADERPERMUTATION_GLOW;
4948 if (r_refdef.fogenabled)
4949 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4950 if (rsurface.texture->colormapping)
4951 permutation |= SHADERPERMUTATION_COLORMAPPING;
4952 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4954 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4955 if (r_shadow_usingshadowmaprect)
4956 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4957 if (r_shadow_usingshadowmap2d)
4958 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4960 if (r_shadow_shadowmapsampler)
4961 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4962 if (r_shadow_shadowmappcf > 1)
4963 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4964 else if (r_shadow_shadowmappcf)
4965 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4967 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4968 permutation |= SHADERPERMUTATION_REFLECTION;
4969 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4970 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4971 if (rsurface.texture->reflectmasktexture)
4972 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4973 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4975 // deluxemapping (light direction texture)
4976 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4977 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4979 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4980 permutation |= SHADERPERMUTATION_DIFFUSE;
4981 if (specularscale > 0)
4983 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4984 if (r_shadow_glossexact.integer)
4985 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4987 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4988 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4989 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4991 R_Mesh_ColorPointer(NULL, 0, 0);
4993 else if (r_glsl_deluxemapping.integer >= 2)
4995 // fake deluxemapping (uniform light direction in tangentspace)
4996 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4997 permutation |= SHADERPERMUTATION_DIFFUSE;
4998 if (specularscale > 0)
5000 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5001 if (r_shadow_glossexact.integer)
5002 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5004 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5005 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5006 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5008 R_Mesh_ColorPointer(NULL, 0, 0);
5010 else if (rsurface.uselightmaptexture)
5012 // ordinary lightmapping (q1bsp, q3bsp)
5013 mode = SHADERMODE_LIGHTMAP;
5014 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5015 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5016 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5018 R_Mesh_ColorPointer(NULL, 0, 0);
5022 // ordinary vertex coloring (q3bsp)
5023 mode = SHADERMODE_VERTEXCOLOR;
5024 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
5025 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5027 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5028 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
5030 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5031 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5032 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5036 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5037 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5038 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5040 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5041 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5043 switch(vid.renderpath)
5045 case RENDERPATH_GL20:
5046 R_SetupShader_SetPermutationGLSL(mode, permutation);
5047 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5048 if (mode == SHADERMODE_LIGHTSOURCE)
5050 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5051 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5052 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5053 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);
5054 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);
5055 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);
5057 // additive passes are only darkened by fog, not tinted
5058 if (r_glsl_permutation->loc_FogColor >= 0)
5059 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5060 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5064 if (mode == SHADERMODE_FLATCOLOR)
5066 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
5068 else if (mode == SHADERMODE_LIGHTDIRECTION)
5070 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]);
5071 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]);
5072 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);
5073 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);
5074 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);
5075 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]);
5076 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]);
5080 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]);
5081 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]);
5082 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);
5083 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);
5084 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);
5086 // additive passes are only darkened by fog, not tinted
5087 if (r_glsl_permutation->loc_FogColor >= 0)
5089 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5090 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5092 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5094 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);
5095 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]);
5096 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]);
5097 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5098 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5099 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5100 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5101 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5103 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5104 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5105 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5106 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]);
5107 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]);
5109 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5110 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5111 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5112 if (r_glsl_permutation->loc_Color_Pants >= 0)
5114 if (rsurface.texture->pantstexture)
5115 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5117 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5119 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5121 if (rsurface.texture->shirttexture)
5122 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5124 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5126 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]);
5127 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5128 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5129 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5130 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5131 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]);
5132 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5134 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5135 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5136 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5137 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5138 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5139 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5140 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5141 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5142 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5143 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5144 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5145 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5146 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5147 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5148 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5149 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5150 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5151 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white );
5152 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_blanknormalmap );
5153 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5154 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , r_texture_white );
5155 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , r_texture_white );
5156 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5157 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5158 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5159 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5160 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5162 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5163 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture );
5164 if (rsurface.rtlight)
5166 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5167 if (r_shadow_usingshadowmapcube)
5168 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5169 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5174 case RENDERPATH_CGGL:
5176 R_SetupShader_SetPermutationCG(mode, permutation);
5177 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5178 if (mode == SHADERMODE_LIGHTSOURCE)
5180 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5181 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5185 if (mode == SHADERMODE_LIGHTDIRECTION)
5187 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
5190 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5191 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5192 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5193 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5194 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
5197 if (mode == SHADERMODE_LIGHTSOURCE)
5199 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5200 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5201 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
5202 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
5203 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
5205 // additive passes are only darkened by fog, not tinted
5206 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5207 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5211 if (mode == SHADERMODE_FLATCOLOR)
5213 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5215 else if (mode == SHADERMODE_LIGHTDIRECTION)
5217 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
5218 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
5219 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
5220 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
5221 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
5222 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
5223 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
5227 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
5228 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
5229 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
5230 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
5231 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
5233 // additive passes are only darkened by fog, not tinted
5234 if (r_cg_permutation->fp_FogColor)
5236 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5237 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5239 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5242 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
5243 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
5244 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
5245 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5246 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5247 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5248 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5249 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5251 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
5252 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
5253 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5254 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5255 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5256 if (r_cg_permutation->fp_Color_Pants)
5258 if (rsurface.texture->pantstexture)
5259 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5261 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5264 if (r_cg_permutation->fp_Color_Shirt)
5266 if (rsurface.texture->shirttexture)
5267 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5269 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5272 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
5273 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5274 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5275 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5276 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5277 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
5278 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5280 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
5281 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
5282 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
5283 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
5284 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
5285 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
5286 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
5287 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
5288 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
5289 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
5290 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
5291 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
5292 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
5293 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
5294 if (r_cg_permutation->fp_Texture_ReflectCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
5295 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
5296 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
5297 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , r_texture_white );CHECKCGERROR
5298 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , r_texture_blanknormalmap );CHECKCGERROR
5299 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5300 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , r_texture_white );CHECKCGERROR
5301 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , r_texture_white );CHECKCGERROR
5302 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5303 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5304 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
5305 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
5306 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5308 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5309 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5310 if (rsurface.rtlight)
5312 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5313 if (r_shadow_usingshadowmapcube)
5314 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5315 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5322 case RENDERPATH_GL13:
5323 case RENDERPATH_GL11:
5328 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5330 // select a permutation of the lighting shader appropriate to this
5331 // combination of texture, entity, light source, and fogging, only use the
5332 // minimum features necessary to avoid wasting rendering time in the
5333 // fragment shader on features that are not being used
5334 unsigned int permutation = 0;
5335 unsigned int mode = 0;
5336 const float *lightcolorbase = rtlight->currentcolor;
5337 float ambientscale = rtlight->ambientscale;
5338 float diffusescale = rtlight->diffusescale;
5339 float specularscale = rtlight->specularscale;
5340 // this is the location of the light in view space
5341 vec3_t viewlightorigin;
5342 // this transforms from view space (camera) to light space (cubemap)
5343 matrix4x4_t viewtolight;
5344 matrix4x4_t lighttoview;
5345 float viewtolight16f[16];
5346 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5348 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5349 if (rtlight->currentcubemap != r_texture_whitecube)
5350 permutation |= SHADERPERMUTATION_CUBEFILTER;
5351 if (diffusescale > 0)
5352 permutation |= SHADERPERMUTATION_DIFFUSE;
5353 if (specularscale > 0)
5355 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5356 if (r_shadow_glossexact.integer)
5357 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5359 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5361 if (r_shadow_usingshadowmaprect)
5362 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5363 if (r_shadow_usingshadowmap2d)
5364 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5365 if (r_shadow_usingshadowmapcube)
5366 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5367 else if(r_shadow_shadowmapvsdct)
5368 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5370 if (r_shadow_shadowmapsampler)
5371 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5372 if (r_shadow_shadowmappcf > 1)
5373 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5374 else if (r_shadow_shadowmappcf)
5375 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5377 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5378 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5379 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5380 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5381 switch(vid.renderpath)
5383 case RENDERPATH_GL20:
5384 R_SetupShader_SetPermutationGLSL(mode, permutation);
5385 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5386 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5387 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);
5388 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);
5389 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);
5390 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]);
5391 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]);
5392 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));
5393 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]);
5394 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5396 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5397 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5398 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5399 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5400 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
5401 if (r_shadow_usingshadowmapcube)
5402 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5403 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5404 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5406 case RENDERPATH_CGGL:
5408 R_SetupShader_SetPermutationCG(mode, permutation);
5409 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5410 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5411 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
5412 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
5413 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
5414 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
5415 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
5416 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
5417 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
5418 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5420 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5421 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5422 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5423 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5424 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5425 if (r_shadow_usingshadowmapcube)
5426 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5427 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5428 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5431 case RENDERPATH_GL13:
5432 case RENDERPATH_GL11:
5437 #define SKINFRAME_HASH 1024
5441 int loadsequence; // incremented each level change
5442 memexpandablearray_t array;
5443 skinframe_t *hash[SKINFRAME_HASH];
5446 r_skinframe_t r_skinframe;
5448 void R_SkinFrame_PrepareForPurge(void)
5450 r_skinframe.loadsequence++;
5451 // wrap it without hitting zero
5452 if (r_skinframe.loadsequence >= 200)
5453 r_skinframe.loadsequence = 1;
5456 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5460 // mark the skinframe as used for the purging code
5461 skinframe->loadsequence = r_skinframe.loadsequence;
5464 void R_SkinFrame_Purge(void)
5468 for (i = 0;i < SKINFRAME_HASH;i++)
5470 for (s = r_skinframe.hash[i];s;s = s->next)
5472 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5474 if (s->merged == s->base)
5476 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5477 R_PurgeTexture(s->stain );s->stain = NULL;
5478 R_PurgeTexture(s->merged);s->merged = NULL;
5479 R_PurgeTexture(s->base );s->base = NULL;
5480 R_PurgeTexture(s->pants );s->pants = NULL;
5481 R_PurgeTexture(s->shirt );s->shirt = NULL;
5482 R_PurgeTexture(s->nmap );s->nmap = NULL;
5483 R_PurgeTexture(s->gloss );s->gloss = NULL;
5484 R_PurgeTexture(s->glow );s->glow = NULL;
5485 R_PurgeTexture(s->fog );s->fog = NULL;
5486 R_PurgeTexture(s->reflect);s->reflect = NULL;
5487 s->loadsequence = 0;
5493 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5495 char basename[MAX_QPATH];
5497 Image_StripImageExtension(name, basename, sizeof(basename));
5499 if( last == NULL ) {
5501 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5502 item = r_skinframe.hash[hashindex];
5507 // linearly search through the hash bucket
5508 for( ; item ; item = item->next ) {
5509 if( !strcmp( item->basename, basename ) ) {
5516 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5520 char basename[MAX_QPATH];
5522 Image_StripImageExtension(name, basename, sizeof(basename));
5524 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5525 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5526 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5530 rtexture_t *dyntexture;
5531 // check whether its a dynamic texture
5532 dyntexture = CL_GetDynTexture( basename );
5533 if (!add && !dyntexture)
5535 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5536 memset(item, 0, sizeof(*item));
5537 strlcpy(item->basename, basename, sizeof(item->basename));
5538 item->base = dyntexture; // either NULL or dyntexture handle
5539 item->textureflags = textureflags;
5540 item->comparewidth = comparewidth;
5541 item->compareheight = compareheight;
5542 item->comparecrc = comparecrc;
5543 item->next = r_skinframe.hash[hashindex];
5544 r_skinframe.hash[hashindex] = item;
5546 else if( item->base == NULL )
5548 rtexture_t *dyntexture;
5549 // check whether its a dynamic texture
5550 // 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]
5551 dyntexture = CL_GetDynTexture( basename );
5552 item->base = dyntexture; // either NULL or dyntexture handle
5555 R_SkinFrame_MarkUsed(item);
5559 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5561 unsigned long long avgcolor[5], wsum; \
5569 for(pix = 0; pix < cnt; ++pix) \
5572 for(comp = 0; comp < 3; ++comp) \
5574 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5577 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5579 for(comp = 0; comp < 3; ++comp) \
5580 avgcolor[comp] += getpixel * w; \
5583 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5584 avgcolor[4] += getpixel; \
5586 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5588 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5589 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5590 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5591 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5594 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5597 unsigned char *pixels;
5598 unsigned char *bumppixels;
5599 unsigned char *basepixels = NULL;
5600 int basepixels_width = 0;
5601 int basepixels_height = 0;
5602 skinframe_t *skinframe;
5603 rtexture_t *ddsbase = NULL;
5604 qboolean ddshasalpha = false;
5605 float ddsavgcolor[4];
5606 char basename[MAX_QPATH];
5608 if (cls.state == ca_dedicated)
5611 // return an existing skinframe if already loaded
5612 // if loading of the first image fails, don't make a new skinframe as it
5613 // would cause all future lookups of this to be missing
5614 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5615 if (skinframe && skinframe->base)
5618 Image_StripImageExtension(name, basename, sizeof(basename));
5620 // check for DDS texture file first
5621 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5623 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5624 if (basepixels == NULL)
5628 if (developer_loading.integer)
5629 Con_Printf("loading skin \"%s\"\n", name);
5631 // we've got some pixels to store, so really allocate this new texture now
5633 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5634 skinframe->stain = NULL;
5635 skinframe->merged = NULL;
5636 skinframe->base = NULL;
5637 skinframe->pants = NULL;
5638 skinframe->shirt = NULL;
5639 skinframe->nmap = NULL;
5640 skinframe->gloss = NULL;
5641 skinframe->glow = NULL;
5642 skinframe->fog = NULL;
5643 skinframe->reflect = NULL;
5644 skinframe->hasalpha = false;
5648 skinframe->base = ddsbase;
5649 skinframe->hasalpha = ddshasalpha;
5650 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5651 if (r_loadfog && skinframe->hasalpha)
5652 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5653 //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]);
5657 basepixels_width = image_width;
5658 basepixels_height = image_height;
5659 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);
5660 if (textureflags & TEXF_ALPHA)
5662 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5664 if (basepixels[j] < 255)
5666 skinframe->hasalpha = true;
5670 if (r_loadfog && skinframe->hasalpha)
5672 // has transparent pixels
5673 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5674 for (j = 0;j < image_width * image_height * 4;j += 4)
5679 pixels[j+3] = basepixels[j+3];
5681 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);
5685 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5686 //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]);
5687 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5688 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5689 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5690 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5695 if (r_loadnormalmap)
5696 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5697 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5699 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5700 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5701 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5702 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5705 // _norm is the name used by tenebrae and has been adopted as standard
5706 if (r_loadnormalmap && skinframe->nmap == NULL)
5708 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5710 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);
5714 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5716 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5717 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5718 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);
5720 Mem_Free(bumppixels);
5722 else if (r_shadow_bumpscale_basetexture.value > 0)
5724 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5725 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5726 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);
5729 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5730 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5733 // _luma is supported only for tenebrae compatibility
5734 // _glow is the preferred name
5735 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))))
5737 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);
5738 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5739 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5740 Mem_Free(pixels);pixels = NULL;
5743 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5745 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);
5746 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5747 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5752 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5754 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);
5755 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5756 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5761 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5763 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);
5764 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5765 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5770 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5772 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5773 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5774 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5780 Mem_Free(basepixels);
5785 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5786 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5789 unsigned char *temp1, *temp2;
5790 skinframe_t *skinframe;
5792 if (cls.state == ca_dedicated)
5795 // if already loaded just return it, otherwise make a new skinframe
5796 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5797 if (skinframe && skinframe->base)
5800 skinframe->stain = NULL;
5801 skinframe->merged = NULL;
5802 skinframe->base = NULL;
5803 skinframe->pants = NULL;
5804 skinframe->shirt = NULL;
5805 skinframe->nmap = NULL;
5806 skinframe->gloss = NULL;
5807 skinframe->glow = NULL;
5808 skinframe->fog = NULL;
5809 skinframe->reflect = NULL;
5810 skinframe->hasalpha = false;
5812 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5816 if (developer_loading.integer)
5817 Con_Printf("loading 32bit skin \"%s\"\n", name);
5819 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5821 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5822 temp2 = temp1 + width * height * 4;
5823 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5824 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5827 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5828 if (textureflags & TEXF_ALPHA)
5830 for (i = 3;i < width * height * 4;i += 4)
5832 if (skindata[i] < 255)
5834 skinframe->hasalpha = true;
5838 if (r_loadfog && skinframe->hasalpha)
5840 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5841 memcpy(fogpixels, skindata, width * height * 4);
5842 for (i = 0;i < width * height * 4;i += 4)
5843 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5844 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5845 Mem_Free(fogpixels);
5849 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5850 //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]);
5855 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5859 skinframe_t *skinframe;
5861 if (cls.state == ca_dedicated)
5864 // if already loaded just return it, otherwise make a new skinframe
5865 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5866 if (skinframe && skinframe->base)
5869 skinframe->stain = NULL;
5870 skinframe->merged = NULL;
5871 skinframe->base = NULL;
5872 skinframe->pants = NULL;
5873 skinframe->shirt = NULL;
5874 skinframe->nmap = NULL;
5875 skinframe->gloss = NULL;
5876 skinframe->glow = NULL;
5877 skinframe->fog = NULL;
5878 skinframe->reflect = NULL;
5879 skinframe->hasalpha = false;
5881 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5885 if (developer_loading.integer)
5886 Con_Printf("loading quake skin \"%s\"\n", name);
5888 // 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)
5889 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5890 memcpy(skinframe->qpixels, skindata, width*height);
5891 skinframe->qwidth = width;
5892 skinframe->qheight = height;
5895 for (i = 0;i < width * height;i++)
5896 featuresmask |= palette_featureflags[skindata[i]];
5898 skinframe->hasalpha = false;
5899 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5900 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5901 skinframe->qgeneratemerged = true;
5902 skinframe->qgeneratebase = skinframe->qhascolormapping;
5903 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5905 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5906 //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]);
5911 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5915 unsigned char *skindata;
5917 if (!skinframe->qpixels)
5920 if (!skinframe->qhascolormapping)
5921 colormapped = false;
5925 if (!skinframe->qgeneratebase)
5930 if (!skinframe->qgeneratemerged)
5934 width = skinframe->qwidth;
5935 height = skinframe->qheight;
5936 skindata = skinframe->qpixels;
5938 if (skinframe->qgeneratenmap)
5940 unsigned char *temp1, *temp2;
5941 skinframe->qgeneratenmap = false;
5942 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5943 temp2 = temp1 + width * height * 4;
5944 // use either a custom palette or the quake palette
5945 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5946 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5947 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5951 if (skinframe->qgenerateglow)
5953 skinframe->qgenerateglow = false;
5954 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5959 skinframe->qgeneratebase = false;
5960 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);
5961 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5962 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5966 skinframe->qgeneratemerged = false;
5967 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5970 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5972 Mem_Free(skinframe->qpixels);
5973 skinframe->qpixels = NULL;
5977 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)
5980 skinframe_t *skinframe;
5982 if (cls.state == ca_dedicated)
5985 // if already loaded just return it, otherwise make a new skinframe
5986 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5987 if (skinframe && skinframe->base)
5990 skinframe->stain = NULL;
5991 skinframe->merged = NULL;
5992 skinframe->base = NULL;
5993 skinframe->pants = NULL;
5994 skinframe->shirt = NULL;
5995 skinframe->nmap = NULL;
5996 skinframe->gloss = NULL;
5997 skinframe->glow = NULL;
5998 skinframe->fog = NULL;
5999 skinframe->reflect = NULL;
6000 skinframe->hasalpha = false;
6002 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6006 if (developer_loading.integer)
6007 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6009 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
6010 if (textureflags & TEXF_ALPHA)
6012 for (i = 0;i < width * height;i++)
6014 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6016 skinframe->hasalpha = true;
6020 if (r_loadfog && skinframe->hasalpha)
6021 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
6024 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6025 //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]);
6030 skinframe_t *R_SkinFrame_LoadMissing(void)
6032 skinframe_t *skinframe;
6034 if (cls.state == ca_dedicated)
6037 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6038 skinframe->stain = NULL;
6039 skinframe->merged = NULL;
6040 skinframe->base = NULL;
6041 skinframe->pants = NULL;
6042 skinframe->shirt = NULL;
6043 skinframe->nmap = NULL;
6044 skinframe->gloss = NULL;
6045 skinframe->glow = NULL;
6046 skinframe->fog = NULL;
6047 skinframe->reflect = NULL;
6048 skinframe->hasalpha = false;
6050 skinframe->avgcolor[0] = rand() / RAND_MAX;
6051 skinframe->avgcolor[1] = rand() / RAND_MAX;
6052 skinframe->avgcolor[2] = rand() / RAND_MAX;
6053 skinframe->avgcolor[3] = 1;
6058 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6059 typedef struct suffixinfo_s
6062 qboolean flipx, flipy, flipdiagonal;
6065 static suffixinfo_t suffix[3][6] =
6068 {"px", false, false, false},
6069 {"nx", false, false, false},
6070 {"py", false, false, false},
6071 {"ny", false, false, false},
6072 {"pz", false, false, false},
6073 {"nz", false, false, false}
6076 {"posx", false, false, false},
6077 {"negx", false, false, false},
6078 {"posy", false, false, false},
6079 {"negy", false, false, false},
6080 {"posz", false, false, false},
6081 {"negz", false, false, false}
6084 {"rt", true, false, true},
6085 {"lf", false, true, true},
6086 {"ft", true, true, false},
6087 {"bk", false, false, false},
6088 {"up", true, false, true},
6089 {"dn", true, false, true}
6093 static int componentorder[4] = {0, 1, 2, 3};
6095 rtexture_t *R_LoadCubemap(const char *basename)
6097 int i, j, cubemapsize;
6098 unsigned char *cubemappixels, *image_buffer;
6099 rtexture_t *cubemaptexture;
6101 // must start 0 so the first loadimagepixels has no requested width/height
6103 cubemappixels = NULL;
6104 cubemaptexture = NULL;
6105 // keep trying different suffix groups (posx, px, rt) until one loads
6106 for (j = 0;j < 3 && !cubemappixels;j++)
6108 // load the 6 images in the suffix group
6109 for (i = 0;i < 6;i++)
6111 // generate an image name based on the base and and suffix
6112 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6114 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
6116 // an image loaded, make sure width and height are equal
6117 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6119 // if this is the first image to load successfully, allocate the cubemap memory
6120 if (!cubemappixels && image_width >= 1)
6122 cubemapsize = image_width;
6123 // note this clears to black, so unavailable sides are black
6124 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6126 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6128 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
6131 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6133 Mem_Free(image_buffer);
6137 // if a cubemap loaded, upload it
6140 if (developer_loading.integer)
6141 Con_Printf("loading cubemap \"%s\"\n", basename);
6143 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
6144 Mem_Free(cubemappixels);
6148 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6149 if (developer_loading.integer)
6151 Con_Printf("(tried tried images ");
6152 for (j = 0;j < 3;j++)
6153 for (i = 0;i < 6;i++)
6154 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6155 Con_Print(" and was unable to find any of them).\n");
6158 return cubemaptexture;
6161 rtexture_t *R_GetCubemap(const char *basename)
6164 for (i = 0;i < r_texture_numcubemaps;i++)
6165 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6166 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6167 if (i >= MAX_CUBEMAPS)
6168 return r_texture_whitecube;
6169 r_texture_numcubemaps++;
6170 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6171 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6172 return r_texture_cubemaps[i].texture;
6175 void R_FreeCubemaps(void)
6178 for (i = 0;i < r_texture_numcubemaps;i++)
6180 if (developer_loading.integer)
6181 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6182 if (r_texture_cubemaps[i].texture)
6183 R_FreeTexture(r_texture_cubemaps[i].texture);
6185 r_texture_numcubemaps = 0;
6188 void R_Main_FreeViewCache(void)
6190 if (r_refdef.viewcache.entityvisible)
6191 Mem_Free(r_refdef.viewcache.entityvisible);
6192 if (r_refdef.viewcache.world_pvsbits)
6193 Mem_Free(r_refdef.viewcache.world_pvsbits);
6194 if (r_refdef.viewcache.world_leafvisible)
6195 Mem_Free(r_refdef.viewcache.world_leafvisible);
6196 if (r_refdef.viewcache.world_surfacevisible)
6197 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6198 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6201 void R_Main_ResizeViewCache(void)
6203 int numentities = r_refdef.scene.numentities;
6204 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6205 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6206 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6207 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6208 if (r_refdef.viewcache.maxentities < numentities)
6210 r_refdef.viewcache.maxentities = numentities;
6211 if (r_refdef.viewcache.entityvisible)
6212 Mem_Free(r_refdef.viewcache.entityvisible);
6213 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6215 if (r_refdef.viewcache.world_numclusters != numclusters)
6217 r_refdef.viewcache.world_numclusters = numclusters;
6218 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6219 if (r_refdef.viewcache.world_pvsbits)
6220 Mem_Free(r_refdef.viewcache.world_pvsbits);
6221 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6223 if (r_refdef.viewcache.world_numleafs != numleafs)
6225 r_refdef.viewcache.world_numleafs = numleafs;
6226 if (r_refdef.viewcache.world_leafvisible)
6227 Mem_Free(r_refdef.viewcache.world_leafvisible);
6228 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6230 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6232 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6233 if (r_refdef.viewcache.world_surfacevisible)
6234 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6235 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6239 extern rtexture_t *loadingscreentexture;
6240 void gl_main_start(void)
6242 loadingscreentexture = NULL;
6243 r_texture_blanknormalmap = NULL;
6244 r_texture_white = NULL;
6245 r_texture_grey128 = NULL;
6246 r_texture_black = NULL;
6247 r_texture_whitecube = NULL;
6248 r_texture_normalizationcube = NULL;
6249 r_texture_fogattenuation = NULL;
6250 r_texture_fogheighttexture = NULL;
6251 r_texture_gammaramps = NULL;
6252 r_texture_numcubemaps = 0;
6254 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6255 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6257 switch(vid.renderpath)
6259 case RENDERPATH_GL20:
6260 case RENDERPATH_CGGL:
6261 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6262 Cvar_SetValueQuick(&gl_combine, 1);
6263 Cvar_SetValueQuick(&r_glsl, 1);
6264 r_loadnormalmap = true;
6268 case RENDERPATH_GL13:
6269 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6270 Cvar_SetValueQuick(&gl_combine, 1);
6271 Cvar_SetValueQuick(&r_glsl, 0);
6272 r_loadnormalmap = false;
6273 r_loadgloss = false;
6276 case RENDERPATH_GL11:
6277 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6278 Cvar_SetValueQuick(&gl_combine, 0);
6279 Cvar_SetValueQuick(&r_glsl, 0);
6280 r_loadnormalmap = false;
6281 r_loadgloss = false;
6287 R_FrameData_Reset();
6291 memset(r_queries, 0, sizeof(r_queries));
6293 r_qwskincache = NULL;
6294 r_qwskincache_size = 0;
6296 // set up r_skinframe loading system for textures
6297 memset(&r_skinframe, 0, sizeof(r_skinframe));
6298 r_skinframe.loadsequence = 1;
6299 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6301 r_main_texturepool = R_AllocTexturePool();
6302 R_BuildBlankTextures();
6304 if (vid.support.arb_texture_cube_map)
6307 R_BuildNormalizationCube();
6309 r_texture_fogattenuation = NULL;
6310 r_texture_fogheighttexture = NULL;
6311 r_texture_gammaramps = NULL;
6312 //r_texture_fogintensity = NULL;
6313 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6314 memset(&r_waterstate, 0, sizeof(r_waterstate));
6315 r_glsl_permutation = NULL;
6316 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6317 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6318 glslshaderstring = NULL;
6320 r_cg_permutation = NULL;
6321 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6322 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6323 cgshaderstring = NULL;
6325 memset(&r_svbsp, 0, sizeof (r_svbsp));
6327 r_refdef.fogmasktable_density = 0;
6330 void gl_main_shutdown(void)
6333 R_FrameData_Reset();
6335 R_Main_FreeViewCache();
6338 qglDeleteQueriesARB(r_maxqueries, r_queries);
6342 memset(r_queries, 0, sizeof(r_queries));
6344 r_qwskincache = NULL;
6345 r_qwskincache_size = 0;
6347 // clear out the r_skinframe state
6348 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6349 memset(&r_skinframe, 0, sizeof(r_skinframe));
6352 Mem_Free(r_svbsp.nodes);
6353 memset(&r_svbsp, 0, sizeof (r_svbsp));
6354 R_FreeTexturePool(&r_main_texturepool);
6355 loadingscreentexture = NULL;
6356 r_texture_blanknormalmap = NULL;
6357 r_texture_white = NULL;
6358 r_texture_grey128 = NULL;
6359 r_texture_black = NULL;
6360 r_texture_whitecube = NULL;
6361 r_texture_normalizationcube = NULL;
6362 r_texture_fogattenuation = NULL;
6363 r_texture_fogheighttexture = NULL;
6364 r_texture_gammaramps = NULL;
6365 r_texture_numcubemaps = 0;
6366 //r_texture_fogintensity = NULL;
6367 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6368 memset(&r_waterstate, 0, sizeof(r_waterstate));
6369 r_glsl_permutation = NULL;
6370 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6371 glslshaderstring = NULL;
6373 r_cg_permutation = NULL;
6374 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6375 cgshaderstring = NULL;
6380 extern void CL_ParseEntityLump(char *entitystring);
6381 void gl_main_newmap(void)
6383 // FIXME: move this code to client
6385 char *entities, entname[MAX_QPATH];
6387 Mem_Free(r_qwskincache);
6388 r_qwskincache = NULL;
6389 r_qwskincache_size = 0;
6392 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6393 l = (int)strlen(entname) - 4;
6394 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6396 memcpy(entname + l, ".ent", 5);
6397 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6399 CL_ParseEntityLump(entities);
6404 if (cl.worldmodel->brush.entities)
6405 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6407 R_Main_FreeViewCache();
6409 R_FrameData_Reset();
6412 void GL_Main_Init(void)
6414 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6416 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6417 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6418 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6419 if (gamemode == GAME_NEHAHRA)
6421 Cvar_RegisterVariable (&gl_fogenable);
6422 Cvar_RegisterVariable (&gl_fogdensity);
6423 Cvar_RegisterVariable (&gl_fogred);
6424 Cvar_RegisterVariable (&gl_foggreen);
6425 Cvar_RegisterVariable (&gl_fogblue);
6426 Cvar_RegisterVariable (&gl_fogstart);
6427 Cvar_RegisterVariable (&gl_fogend);
6428 Cvar_RegisterVariable (&gl_skyclip);
6430 Cvar_RegisterVariable(&r_motionblur);
6431 Cvar_RegisterVariable(&r_motionblur_maxblur);
6432 Cvar_RegisterVariable(&r_motionblur_bmin);
6433 Cvar_RegisterVariable(&r_motionblur_vmin);
6434 Cvar_RegisterVariable(&r_motionblur_vmax);
6435 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6436 Cvar_RegisterVariable(&r_motionblur_randomize);
6437 Cvar_RegisterVariable(&r_damageblur);
6438 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6439 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6440 Cvar_RegisterVariable(&r_equalize_entities_by);
6441 Cvar_RegisterVariable(&r_equalize_entities_to);
6442 Cvar_RegisterVariable(&r_depthfirst);
6443 Cvar_RegisterVariable(&r_useinfinitefarclip);
6444 Cvar_RegisterVariable(&r_farclip_base);
6445 Cvar_RegisterVariable(&r_farclip_world);
6446 Cvar_RegisterVariable(&r_nearclip);
6447 Cvar_RegisterVariable(&r_showbboxes);
6448 Cvar_RegisterVariable(&r_showsurfaces);
6449 Cvar_RegisterVariable(&r_showtris);
6450 Cvar_RegisterVariable(&r_shownormals);
6451 Cvar_RegisterVariable(&r_showlighting);
6452 Cvar_RegisterVariable(&r_showshadowvolumes);
6453 Cvar_RegisterVariable(&r_showcollisionbrushes);
6454 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6455 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6456 Cvar_RegisterVariable(&r_showdisabledepthtest);
6457 Cvar_RegisterVariable(&r_drawportals);
6458 Cvar_RegisterVariable(&r_drawentities);
6459 Cvar_RegisterVariable(&r_cullentities_trace);
6460 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6461 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6462 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6463 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6464 Cvar_RegisterVariable(&r_drawviewmodel);
6465 Cvar_RegisterVariable(&r_drawexteriormodel);
6466 Cvar_RegisterVariable(&r_speeds);
6467 Cvar_RegisterVariable(&r_fullbrights);
6468 Cvar_RegisterVariable(&r_wateralpha);
6469 Cvar_RegisterVariable(&r_dynamic);
6470 Cvar_RegisterVariable(&r_fullbright);
6471 Cvar_RegisterVariable(&r_shadows);
6472 Cvar_RegisterVariable(&r_shadows_darken);
6473 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6474 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6475 Cvar_RegisterVariable(&r_shadows_throwdistance);
6476 Cvar_RegisterVariable(&r_shadows_throwdirection);
6477 Cvar_RegisterVariable(&r_shadows_focus);
6478 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6479 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6480 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6481 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6482 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6483 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6484 Cvar_RegisterVariable(&r_fog_exp2);
6485 Cvar_RegisterVariable(&r_drawfog);
6486 Cvar_RegisterVariable(&r_transparentdepthmasking);
6487 Cvar_RegisterVariable(&r_texture_dds_load);
6488 Cvar_RegisterVariable(&r_texture_dds_save);
6489 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6490 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6491 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6492 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6493 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6494 Cvar_RegisterVariable(&r_textureunits);
6495 Cvar_RegisterVariable(&gl_combine);
6496 Cvar_RegisterVariable(&r_glsl);
6497 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6498 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6499 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6500 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6501 Cvar_RegisterVariable(&r_glsl_postprocess);
6502 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6503 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6504 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6505 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6506 // Cvar_RegisterVariable(&r_glsl_postprocess_sobel);
6507 Cvar_RegisterVariable(&r_water);
6508 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6509 Cvar_RegisterVariable(&r_water_clippingplanebias);
6510 Cvar_RegisterVariable(&r_water_refractdistort);
6511 Cvar_RegisterVariable(&r_water_reflectdistort);
6512 Cvar_RegisterVariable(&r_lerpsprites);
6513 Cvar_RegisterVariable(&r_lerpmodels);
6514 Cvar_RegisterVariable(&r_lerplightstyles);
6515 Cvar_RegisterVariable(&r_waterscroll);
6516 Cvar_RegisterVariable(&r_bloom);
6517 Cvar_RegisterVariable(&r_bloom_colorscale);
6518 Cvar_RegisterVariable(&r_bloom_brighten);
6519 Cvar_RegisterVariable(&r_bloom_blur);
6520 Cvar_RegisterVariable(&r_bloom_resolution);
6521 Cvar_RegisterVariable(&r_bloom_colorexponent);
6522 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6523 Cvar_RegisterVariable(&r_hdr);
6524 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6525 Cvar_RegisterVariable(&r_hdr_glowintensity);
6526 Cvar_RegisterVariable(&r_hdr_range);
6527 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6528 Cvar_RegisterVariable(&developer_texturelogging);
6529 Cvar_RegisterVariable(&gl_lightmaps);
6530 Cvar_RegisterVariable(&r_test);
6531 Cvar_RegisterVariable(&r_batchmode);
6532 Cvar_RegisterVariable(&r_glsl_saturation);
6533 Cvar_RegisterVariable(&r_framedatasize);
6534 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6535 Cvar_SetValue("r_fullbrights", 0);
6536 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6538 Cvar_RegisterVariable(&r_track_sprites);
6539 Cvar_RegisterVariable(&r_track_sprites_flags);
6540 Cvar_RegisterVariable(&r_track_sprites_scalew);
6541 Cvar_RegisterVariable(&r_track_sprites_scaleh);
6542 Cvar_RegisterVariable(&r_overheadsprites_perspective);
6543 Cvar_RegisterVariable(&r_overheadsprites_pushback);
6546 extern void R_Textures_Init(void);
6547 extern void GL_Draw_Init(void);
6548 extern void GL_Main_Init(void);
6549 extern void R_Shadow_Init(void);
6550 extern void R_Sky_Init(void);
6551 extern void GL_Surf_Init(void);
6552 extern void R_Particles_Init(void);
6553 extern void R_Explosion_Init(void);
6554 extern void gl_backend_init(void);
6555 extern void Sbar_Init(void);
6556 extern void R_LightningBeams_Init(void);
6557 extern void Mod_RenderInit(void);
6558 extern void Font_Init(void);
6560 void Render_Init(void)
6573 R_LightningBeams_Init();
6582 extern char *ENGINE_EXTENSIONS;
6585 gl_renderer = (const char *)qglGetString(GL_RENDERER);
6586 gl_vendor = (const char *)qglGetString(GL_VENDOR);
6587 gl_version = (const char *)qglGetString(GL_VERSION);
6588 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6592 if (!gl_platformextensions)
6593 gl_platformextensions = "";
6595 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6596 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6597 Con_Printf("GL_VERSION: %s\n", gl_version);
6598 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6599 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6601 VID_CheckExtensions();
6603 // LordHavoc: report supported extensions
6604 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6606 // clear to black (loading plaque will be seen over this)
6608 qglClearColor(0,0,0,1);CHECKGLERROR
6609 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6612 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6616 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6618 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6621 p = r_refdef.view.frustum + i;
6626 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6630 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6634 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6638 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6642 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6646 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6650 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6654 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6662 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6666 for (i = 0;i < numplanes;i++)
6673 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6677 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6681 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6685 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6689 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6693 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6697 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6701 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6709 //==================================================================================
6711 // LordHavoc: this stores temporary data used within the same frame
6713 qboolean r_framedata_failed;
6714 static size_t r_framedata_size;
6715 static size_t r_framedata_current;
6716 static void *r_framedata_base;
6718 void R_FrameData_Reset(void)
6720 if (r_framedata_base)
6721 Mem_Free(r_framedata_base);
6722 r_framedata_base = NULL;
6723 r_framedata_size = 0;
6724 r_framedata_current = 0;
6725 r_framedata_failed = false;
6728 void R_FrameData_NewFrame(void)
6731 if (r_framedata_failed)
6732 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6733 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6734 wantedsize = bound(65536, wantedsize, 128*1024*1024);
6735 if (r_framedata_size != wantedsize)
6737 r_framedata_size = wantedsize;
6738 if (r_framedata_base)
6739 Mem_Free(r_framedata_base);
6740 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6742 r_framedata_current = 0;
6743 r_framedata_failed = false;
6746 void *R_FrameData_Alloc(size_t size)
6750 // align to 16 byte boundary
6751 size = (size + 15) & ~15;
6752 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6753 r_framedata_current += size;
6756 if (r_framedata_current > r_framedata_size)
6757 r_framedata_failed = true;
6759 // return NULL on everything after a failure
6760 if (r_framedata_failed)
6766 void *R_FrameData_Store(size_t size, void *data)
6768 void *d = R_FrameData_Alloc(size);
6770 memcpy(d, data, size);
6774 //==================================================================================
6776 // LordHavoc: animcache originally written by Echon, rewritten since then
6779 * Animation cache prevents re-generating mesh data for an animated model
6780 * multiple times in one frame for lighting, shadowing, reflections, etc.
6783 void R_AnimCache_Free(void)
6787 void R_AnimCache_ClearCache(void)
6790 entity_render_t *ent;
6792 for (i = 0;i < r_refdef.scene.numentities;i++)
6794 ent = r_refdef.scene.entities[i];
6795 ent->animcache_vertex3f = NULL;
6796 ent->animcache_normal3f = NULL;
6797 ent->animcache_svector3f = NULL;
6798 ent->animcache_tvector3f = NULL;
6802 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6804 dp_model_t *model = ent->model;
6806 // see if it's already cached this frame
6807 if (ent->animcache_vertex3f)
6809 // add normals/tangents if needed
6810 if (wantnormals || wanttangents)
6812 if (ent->animcache_normal3f)
6813 wantnormals = false;
6814 if (ent->animcache_svector3f)
6815 wanttangents = false;
6816 if (wantnormals || wanttangents)
6818 numvertices = model->surfmesh.num_vertices;
6820 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6823 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6824 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6826 if (!r_framedata_failed)
6827 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6833 // see if this ent is worth caching
6834 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6836 // get some memory for this entity and generate mesh data
6837 numvertices = model->surfmesh.num_vertices;
6838 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6840 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6843 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6844 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6846 if (!r_framedata_failed)
6847 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6849 return !r_framedata_failed;
6852 void R_AnimCache_CacheVisibleEntities(void)
6855 qboolean wantnormals = !r_showsurfaces.integer;
6856 qboolean wanttangents = !r_showsurfaces.integer;
6858 switch(vid.renderpath)
6860 case RENDERPATH_GL20:
6861 case RENDERPATH_CGGL:
6863 case RENDERPATH_GL13:
6864 case RENDERPATH_GL11:
6865 wanttangents = false;
6869 // TODO: thread this
6870 // NOTE: R_PrepareRTLights() also caches entities
6872 for (i = 0;i < r_refdef.scene.numentities;i++)
6873 if (r_refdef.viewcache.entityvisible[i])
6874 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6877 //==================================================================================
6879 static void R_View_UpdateEntityLighting (void)
6882 entity_render_t *ent;
6883 vec3_t tempdiffusenormal, avg;
6884 vec_t f, fa, fd, fdd;
6885 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
6887 for (i = 0;i < r_refdef.scene.numentities;i++)
6889 ent = r_refdef.scene.entities[i];
6891 // skip unseen models
6892 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6896 if (ent->model && ent->model->brush.num_leafs)
6898 // TODO: use modellight for r_ambient settings on world?
6899 VectorSet(ent->modellight_ambient, 0, 0, 0);
6900 VectorSet(ent->modellight_diffuse, 0, 0, 0);
6901 VectorSet(ent->modellight_lightdir, 0, 0, 1);
6905 // fetch the lighting from the worldmodel data
6906 VectorClear(ent->modellight_ambient);
6907 VectorClear(ent->modellight_diffuse);
6908 VectorClear(tempdiffusenormal);
6909 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6912 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6913 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6914 if(ent->flags & RENDER_EQUALIZE)
6916 // first fix up ambient lighting...
6917 if(r_equalize_entities_minambient.value > 0)
6919 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6922 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6923 if(fa < r_equalize_entities_minambient.value * fd)
6926 // fa'/fd' = minambient
6927 // fa'+0.25*fd' = fa+0.25*fd
6929 // fa' = fd' * minambient
6930 // fd'*(0.25+minambient) = fa+0.25*fd
6932 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6933 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6935 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6936 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
6937 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6938 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6943 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6945 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6946 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6949 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6950 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6951 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6957 VectorSet(ent->modellight_ambient, 1, 1, 1);
6959 // move the light direction into modelspace coordinates for lighting code
6960 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6961 if(VectorLength2(ent->modellight_lightdir) == 0)
6962 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6963 VectorNormalize(ent->modellight_lightdir);
6967 #define MAX_LINEOFSIGHTTRACES 64
6969 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6972 vec3_t boxmins, boxmaxs;
6975 dp_model_t *model = r_refdef.scene.worldmodel;
6977 if (!model || !model->brush.TraceLineOfSight)
6980 // expand the box a little
6981 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6982 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6983 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6984 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6985 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6986 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6988 // return true if eye is inside enlarged box
6989 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6993 VectorCopy(eye, start);
6994 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6995 if (model->brush.TraceLineOfSight(model, start, end))
6998 // try various random positions
6999 for (i = 0;i < numsamples;i++)
7001 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7002 if (model->brush.TraceLineOfSight(model, start, end))
7010 static void R_View_UpdateEntityVisible (void)
7015 entity_render_t *ent;
7017 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7018 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7019 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7020 : RENDER_EXTERIORMODEL;
7021 if (!r_drawviewmodel.integer)
7022 renderimask |= RENDER_VIEWMODEL;
7023 if (!r_drawexteriormodel.integer)
7024 renderimask |= RENDER_EXTERIORMODEL;
7025 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7027 // worldmodel can check visibility
7028 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7029 for (i = 0;i < r_refdef.scene.numentities;i++)
7031 ent = r_refdef.scene.entities[i];
7032 if (!(ent->flags & renderimask))
7033 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)))
7034 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))
7035 r_refdef.viewcache.entityvisible[i] = true;
7037 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7038 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7040 for (i = 0;i < r_refdef.scene.numentities;i++)
7042 ent = r_refdef.scene.entities[i];
7043 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7045 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7047 continue; // temp entities do pvs only
7048 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7049 ent->last_trace_visibility = realtime;
7050 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7051 r_refdef.viewcache.entityvisible[i] = 0;
7058 // no worldmodel or it can't check visibility
7059 for (i = 0;i < r_refdef.scene.numentities;i++)
7061 ent = r_refdef.scene.entities[i];
7062 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));
7067 /// only used if skyrendermasked, and normally returns false
7068 int R_DrawBrushModelsSky (void)
7071 entity_render_t *ent;
7074 for (i = 0;i < r_refdef.scene.numentities;i++)
7076 if (!r_refdef.viewcache.entityvisible[i])
7078 ent = r_refdef.scene.entities[i];
7079 if (!ent->model || !ent->model->DrawSky)
7081 ent->model->DrawSky(ent);
7087 static void R_DrawNoModel(entity_render_t *ent);
7088 static void R_DrawModels(void)
7091 entity_render_t *ent;
7093 for (i = 0;i < r_refdef.scene.numentities;i++)
7095 if (!r_refdef.viewcache.entityvisible[i])
7097 ent = r_refdef.scene.entities[i];
7098 r_refdef.stats.entities++;
7099 if (ent->model && ent->model->Draw != NULL)
7100 ent->model->Draw(ent);
7106 static void R_DrawModelsDepth(void)
7109 entity_render_t *ent;
7111 for (i = 0;i < r_refdef.scene.numentities;i++)
7113 if (!r_refdef.viewcache.entityvisible[i])
7115 ent = r_refdef.scene.entities[i];
7116 if (ent->model && ent->model->DrawDepth != NULL)
7117 ent->model->DrawDepth(ent);
7121 static void R_DrawModelsDebug(void)
7124 entity_render_t *ent;
7126 for (i = 0;i < r_refdef.scene.numentities;i++)
7128 if (!r_refdef.viewcache.entityvisible[i])
7130 ent = r_refdef.scene.entities[i];
7131 if (ent->model && ent->model->DrawDebug != NULL)
7132 ent->model->DrawDebug(ent);
7136 static void R_DrawModelsAddWaterPlanes(void)
7139 entity_render_t *ent;
7141 for (i = 0;i < r_refdef.scene.numentities;i++)
7143 if (!r_refdef.viewcache.entityvisible[i])
7145 ent = r_refdef.scene.entities[i];
7146 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7147 ent->model->DrawAddWaterPlanes(ent);
7151 static void R_View_SetFrustum(void)
7154 double slopex, slopey;
7155 vec3_t forward, left, up, origin;
7157 // we can't trust r_refdef.view.forward and friends in reflected scenes
7158 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7161 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7162 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7163 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7164 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7165 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7166 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7167 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7168 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7169 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7170 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7171 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7172 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7176 zNear = r_refdef.nearclip;
7177 nudge = 1.0 - 1.0 / (1<<23);
7178 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7179 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7180 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7181 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7182 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7183 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7184 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7185 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7191 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7192 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7193 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7194 r_refdef.view.frustum[0].dist = m[15] - m[12];
7196 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7197 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7198 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7199 r_refdef.view.frustum[1].dist = m[15] + m[12];
7201 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7202 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7203 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7204 r_refdef.view.frustum[2].dist = m[15] - m[13];
7206 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7207 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7208 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7209 r_refdef.view.frustum[3].dist = m[15] + m[13];
7211 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7212 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7213 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7214 r_refdef.view.frustum[4].dist = m[15] - m[14];
7216 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7217 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7218 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7219 r_refdef.view.frustum[5].dist = m[15] + m[14];
7222 if (r_refdef.view.useperspective)
7224 slopex = 1.0 / r_refdef.view.frustum_x;
7225 slopey = 1.0 / r_refdef.view.frustum_y;
7226 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7227 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
7228 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
7229 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
7230 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7232 // Leaving those out was a mistake, those were in the old code, and they
7233 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7234 // I couldn't reproduce it after adding those normalizations. --blub
7235 VectorNormalize(r_refdef.view.frustum[0].normal);
7236 VectorNormalize(r_refdef.view.frustum[1].normal);
7237 VectorNormalize(r_refdef.view.frustum[2].normal);
7238 VectorNormalize(r_refdef.view.frustum[3].normal);
7240 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7241 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]);
7242 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]);
7243 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]);
7244 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]);
7246 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7247 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7248 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7249 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7250 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7254 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7255 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7256 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7257 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7258 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7259 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7260 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7261 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7262 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7263 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7265 r_refdef.view.numfrustumplanes = 5;
7267 if (r_refdef.view.useclipplane)
7269 r_refdef.view.numfrustumplanes = 6;
7270 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7273 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7274 PlaneClassify(r_refdef.view.frustum + i);
7276 // LordHavoc: note to all quake engine coders, Quake had a special case
7277 // for 90 degrees which assumed a square view (wrong), so I removed it,
7278 // Quake2 has it disabled as well.
7280 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7281 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7282 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7283 //PlaneClassify(&frustum[0]);
7285 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7286 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7287 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7288 //PlaneClassify(&frustum[1]);
7290 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7291 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7292 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7293 //PlaneClassify(&frustum[2]);
7295 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7296 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7297 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7298 //PlaneClassify(&frustum[3]);
7301 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7302 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7303 //PlaneClassify(&frustum[4]);
7306 void R_View_Update(void)
7308 R_Main_ResizeViewCache();
7309 R_View_SetFrustum();
7310 R_View_WorldVisibility(r_refdef.view.useclipplane);
7311 R_View_UpdateEntityVisible();
7312 R_View_UpdateEntityLighting();
7315 void R_SetupView(qboolean allowwaterclippingplane)
7317 const float *customclipplane = NULL;
7319 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7321 // LordHavoc: couldn't figure out how to make this approach the
7322 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7323 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7324 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7325 dist = r_refdef.view.clipplane.dist;
7326 plane[0] = r_refdef.view.clipplane.normal[0];
7327 plane[1] = r_refdef.view.clipplane.normal[1];
7328 plane[2] = r_refdef.view.clipplane.normal[2];
7330 customclipplane = plane;
7333 if (!r_refdef.view.useperspective)
7334 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);
7335 else if (vid.stencil && r_useinfinitefarclip.integer)
7336 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);
7338 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);
7339 R_SetViewport(&r_refdef.view.viewport);
7342 void R_EntityMatrix(const matrix4x4_t *matrix)
7344 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7346 gl_modelmatrixchanged = false;
7347 gl_modelmatrix = *matrix;
7348 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7349 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7350 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7351 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7353 switch(vid.renderpath)
7355 case RENDERPATH_GL20:
7356 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7357 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7358 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7360 case RENDERPATH_CGGL:
7363 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7364 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7365 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7368 case RENDERPATH_GL13:
7369 case RENDERPATH_GL11:
7370 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7376 void R_ResetViewRendering2D(void)
7378 r_viewport_t viewport;
7381 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7382 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);
7383 R_SetViewport(&viewport);
7384 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7385 GL_Color(1, 1, 1, 1);
7386 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7387 GL_BlendFunc(GL_ONE, GL_ZERO);
7388 GL_AlphaTest(false);
7389 GL_ScissorTest(false);
7390 GL_DepthMask(false);
7391 GL_DepthRange(0, 1);
7392 GL_DepthTest(false);
7393 R_EntityMatrix(&identitymatrix);
7394 R_Mesh_ResetTextureState();
7395 GL_PolygonOffset(0, 0);
7396 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7397 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7398 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7399 qglStencilMask(~0);CHECKGLERROR
7400 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7401 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7402 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7405 void R_ResetViewRendering3D(void)
7410 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7411 GL_Color(1, 1, 1, 1);
7412 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7413 GL_BlendFunc(GL_ONE, GL_ZERO);
7414 GL_AlphaTest(false);
7415 GL_ScissorTest(true);
7417 GL_DepthRange(0, 1);
7419 R_EntityMatrix(&identitymatrix);
7420 R_Mesh_ResetTextureState();
7421 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7422 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7423 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7424 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7425 qglStencilMask(~0);CHECKGLERROR
7426 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7427 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7428 GL_CullFace(r_refdef.view.cullface_back);
7433 R_RenderView_UpdateViewVectors
7436 static void R_RenderView_UpdateViewVectors(void)
7438 // break apart the view matrix into vectors for various purposes
7439 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7440 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7441 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7442 VectorNegate(r_refdef.view.left, r_refdef.view.right);
7443 // make an inverted copy of the view matrix for tracking sprites
7444 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7447 void R_RenderScene(void);
7448 void R_RenderWaterPlanes(void);
7450 static void R_Water_StartFrame(void)
7453 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
7454 r_waterstate_waterplane_t *p;
7456 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7459 switch(vid.renderpath)
7461 case RENDERPATH_GL20:
7462 case RENDERPATH_CGGL:
7464 case RENDERPATH_GL13:
7465 case RENDERPATH_GL11:
7469 // set waterwidth and waterheight to the water resolution that will be
7470 // used (often less than the screen resolution for faster rendering)
7471 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7472 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7474 // calculate desired texture sizes
7475 // can't use water if the card does not support the texture size
7476 if (!r_water.integer || r_showsurfaces.integer)
7477 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
7478 else if (vid.support.arb_texture_non_power_of_two)
7480 texturewidth = waterwidth;
7481 textureheight = waterheight;
7482 camerawidth = waterwidth;
7483 cameraheight = waterheight;
7487 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
7488 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
7489 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
7490 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
7493 // allocate textures as needed
7494 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
7496 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7497 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7499 if (p->texture_refraction)
7500 R_FreeTexture(p->texture_refraction);
7501 p->texture_refraction = NULL;
7502 if (p->texture_reflection)
7503 R_FreeTexture(p->texture_reflection);
7504 p->texture_reflection = NULL;
7505 if (p->texture_camera)
7506 R_FreeTexture(p->texture_camera);
7507 p->texture_camera = NULL;
7509 memset(&r_waterstate, 0, sizeof(r_waterstate));
7510 r_waterstate.texturewidth = texturewidth;
7511 r_waterstate.textureheight = textureheight;
7512 r_waterstate.camerawidth = camerawidth;
7513 r_waterstate.cameraheight = cameraheight;
7516 if (r_waterstate.texturewidth)
7518 r_waterstate.enabled = true;
7520 // when doing a reduced render (HDR) we want to use a smaller area
7521 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7522 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7524 // set up variables that will be used in shader setup
7525 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7526 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7527 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7528 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7531 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7532 r_waterstate.numwaterplanes = 0;
7535 void R_Water_AddWaterPlane(msurface_t *surface)
7537 int triangleindex, planeindex;
7544 r_waterstate_waterplane_t *p;
7545 texture_t *t = R_GetCurrentTexture(surface->texture);
7546 cam_ent = t->camera_entity;
7547 if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
7550 // just use the first triangle with a valid normal for any decisions
7551 VectorClear(normal);
7552 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7554 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7555 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7556 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7557 TriangleNormal(vert[0], vert[1], vert[2], normal);
7558 if (VectorLength2(normal) >= 0.001)
7562 VectorCopy(normal, plane.normal);
7563 VectorNormalize(plane.normal);
7564 plane.dist = DotProduct(vert[0], plane.normal);
7565 PlaneClassify(&plane);
7566 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7568 // skip backfaces (except if nocullface is set)
7569 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7571 VectorNegate(plane.normal, plane.normal);
7573 PlaneClassify(&plane);
7577 // find a matching plane if there is one
7578 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7579 if(p->camera_entity == t->camera_entity)
7580 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7582 if (planeindex >= r_waterstate.maxwaterplanes)
7583 return; // nothing we can do, out of planes
7585 // if this triangle does not fit any known plane rendered this frame, add one
7586 if (planeindex >= r_waterstate.numwaterplanes)
7588 // store the new plane
7589 r_waterstate.numwaterplanes++;
7591 // clear materialflags and pvs
7592 p->materialflags = 0;
7593 p->pvsvalid = false;
7594 p->camera_entity = t->camera_entity;
7596 // merge this surface's materialflags into the waterplane
7597 p->materialflags |= t->currentmaterialflags;
7598 if(!(p->materialflags & MATERIALFLAG_CAMERA))
7600 // merge this surface's PVS into the waterplane
7601 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7602 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7603 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7605 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7611 static void R_Water_ProcessPlanes(void)
7613 r_refdef_view_t originalview;
7614 r_refdef_view_t myview;
7616 r_waterstate_waterplane_t *p;
7619 originalview = r_refdef.view;
7621 // make sure enough textures are allocated
7622 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7624 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7626 if (!p->texture_refraction)
7627 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);
7628 if (!p->texture_refraction)
7631 else if (p->materialflags & MATERIALFLAG_CAMERA)
7633 if (!p->texture_camera)
7634 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, NULL);
7635 if (!p->texture_camera)
7639 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7641 if (!p->texture_reflection)
7642 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);
7643 if (!p->texture_reflection)
7649 r_refdef.view = originalview;
7650 r_refdef.view.showdebug = false;
7651 r_refdef.view.width = r_waterstate.waterwidth;
7652 r_refdef.view.height = r_waterstate.waterheight;
7653 r_refdef.view.useclipplane = true;
7654 myview = r_refdef.view;
7655 r_waterstate.renderingscene = true;
7656 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7658 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7660 r_refdef.view = myview;
7661 // render reflected scene and copy into texture
7662 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7663 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7664 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7665 r_refdef.view.clipplane = p->plane;
7666 // reverse the cullface settings for this render
7667 r_refdef.view.cullface_front = GL_FRONT;
7668 r_refdef.view.cullface_back = GL_BACK;
7669 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7671 r_refdef.view.usecustompvs = true;
7673 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7675 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7678 R_ResetViewRendering3D();
7679 R_ClearScreen(r_refdef.fogenabled);
7683 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);
7686 // render the normal view scene and copy into texture
7687 // (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)
7688 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7690 r_waterstate.renderingrefraction = true;
7691 r_refdef.view = myview;
7693 r_refdef.view.clipplane = p->plane;
7694 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7695 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7697 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
7699 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7700 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
7701 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7702 R_RenderView_UpdateViewVectors();
7703 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
7706 PlaneClassify(&r_refdef.view.clipplane);
7708 R_ResetViewRendering3D();
7709 R_ClearScreen(r_refdef.fogenabled);
7713 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);
7714 r_waterstate.renderingrefraction = false;
7716 else if (p->materialflags & MATERIALFLAG_CAMERA)
7718 r_refdef.view = myview;
7720 r_refdef.view.clipplane = p->plane;
7721 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7722 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7724 r_refdef.view.width = r_waterstate.camerawidth;
7725 r_refdef.view.height = r_waterstate.cameraheight;
7726 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
7727 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
7729 if(p->camera_entity)
7731 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7732 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7735 // reverse the cullface settings for this render
7736 r_refdef.view.cullface_front = GL_FRONT;
7737 r_refdef.view.cullface_back = GL_BACK;
7738 // also reverse the view matrix
7739 Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, -1, 1);
7740 R_RenderView_UpdateViewVectors();
7741 if(p->camera_entity)
7742 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
7744 // camera needs no clipplane
7745 r_refdef.view.useclipplane = false;
7747 PlaneClassify(&r_refdef.view.clipplane);
7749 R_ResetViewRendering3D();
7750 R_ClearScreen(r_refdef.fogenabled);
7754 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7755 r_waterstate.renderingrefraction = false;
7759 r_waterstate.renderingscene = false;
7760 r_refdef.view = originalview;
7761 R_ResetViewRendering3D();
7762 R_ClearScreen(r_refdef.fogenabled);
7766 r_refdef.view = originalview;
7767 r_waterstate.renderingscene = false;
7768 Cvar_SetValueQuick(&r_water, 0);
7769 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
7773 void R_Bloom_StartFrame(void)
7775 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7777 switch(vid.renderpath)
7779 case RENDERPATH_GL20:
7780 case RENDERPATH_CGGL:
7782 case RENDERPATH_GL13:
7783 case RENDERPATH_GL11:
7787 // set bloomwidth and bloomheight to the bloom resolution that will be
7788 // used (often less than the screen resolution for faster rendering)
7789 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7790 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7791 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7792 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7793 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7795 // calculate desired texture sizes
7796 if (vid.support.arb_texture_non_power_of_two)
7798 screentexturewidth = r_refdef.view.width;
7799 screentextureheight = r_refdef.view.height;
7800 bloomtexturewidth = r_bloomstate.bloomwidth;
7801 bloomtextureheight = r_bloomstate.bloomheight;
7805 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
7806 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
7807 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
7808 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
7811 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))
7813 Cvar_SetValueQuick(&r_hdr, 0);
7814 Cvar_SetValueQuick(&r_bloom, 0);
7815 Cvar_SetValueQuick(&r_motionblur, 0);
7816 Cvar_SetValueQuick(&r_damageblur, 0);
7819 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)))
7820 screentexturewidth = screentextureheight = 0;
7821 if (!r_hdr.integer && !r_bloom.integer)
7822 bloomtexturewidth = bloomtextureheight = 0;
7824 // allocate textures as needed
7825 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7827 if (r_bloomstate.texture_screen)
7828 R_FreeTexture(r_bloomstate.texture_screen);
7829 r_bloomstate.texture_screen = NULL;
7830 r_bloomstate.screentexturewidth = screentexturewidth;
7831 r_bloomstate.screentextureheight = screentextureheight;
7832 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7833 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7835 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7837 if (r_bloomstate.texture_bloom)
7838 R_FreeTexture(r_bloomstate.texture_bloom);
7839 r_bloomstate.texture_bloom = NULL;
7840 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7841 r_bloomstate.bloomtextureheight = bloomtextureheight;
7842 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7843 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7846 // when doing a reduced render (HDR) we want to use a smaller area
7847 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7848 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7849 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7850 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7851 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7853 // set up a texcoord array for the full resolution screen image
7854 // (we have to keep this around to copy back during final render)
7855 r_bloomstate.screentexcoord2f[0] = 0;
7856 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7857 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7858 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7859 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7860 r_bloomstate.screentexcoord2f[5] = 0;
7861 r_bloomstate.screentexcoord2f[6] = 0;
7862 r_bloomstate.screentexcoord2f[7] = 0;
7864 // set up a texcoord array for the reduced resolution bloom image
7865 // (which will be additive blended over the screen image)
7866 r_bloomstate.bloomtexcoord2f[0] = 0;
7867 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7868 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7869 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7870 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7871 r_bloomstate.bloomtexcoord2f[5] = 0;
7872 r_bloomstate.bloomtexcoord2f[6] = 0;
7873 r_bloomstate.bloomtexcoord2f[7] = 0;
7875 if (r_hdr.integer || r_bloom.integer)
7877 r_bloomstate.enabled = true;
7878 r_bloomstate.hdr = r_hdr.integer != 0;
7881 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);
7884 void R_Bloom_CopyBloomTexture(float colorscale)
7886 r_refdef.stats.bloom++;
7888 // scale down screen texture to the bloom texture size
7890 R_SetViewport(&r_bloomstate.viewport);
7891 GL_BlendFunc(GL_ONE, GL_ZERO);
7892 GL_Color(colorscale, colorscale, colorscale, 1);
7893 // TODO: optimize with multitexture or GLSL
7894 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7895 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7896 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7897 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7899 // we now have a bloom image in the framebuffer
7900 // copy it into the bloom image texture for later processing
7901 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);
7902 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7905 void R_Bloom_CopyHDRTexture(void)
7907 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);
7908 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7911 void R_Bloom_MakeTexture(void)
7914 float xoffset, yoffset, r, brighten;
7916 r_refdef.stats.bloom++;
7918 R_ResetViewRendering2D();
7919 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7920 R_Mesh_ColorPointer(NULL, 0, 0);
7922 // we have a bloom image in the framebuffer
7924 R_SetViewport(&r_bloomstate.viewport);
7926 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7929 r = bound(0, r_bloom_colorexponent.value / x, 1);
7930 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7931 GL_Color(r, r, r, 1);
7932 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7933 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7934 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7935 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7937 // copy the vertically blurred bloom view to a texture
7938 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);
7939 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7942 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7943 brighten = r_bloom_brighten.value;
7945 brighten *= r_hdr_range.value;
7946 brighten = sqrt(brighten);
7948 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7949 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7950 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7952 for (dir = 0;dir < 2;dir++)
7954 // blend on at multiple vertical offsets to achieve a vertical blur
7955 // TODO: do offset blends using GLSL
7956 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7957 GL_BlendFunc(GL_ONE, GL_ZERO);
7958 for (x = -range;x <= range;x++)
7960 if (!dir){xoffset = 0;yoffset = x;}
7961 else {xoffset = x;yoffset = 0;}
7962 xoffset /= (float)r_bloomstate.bloomtexturewidth;
7963 yoffset /= (float)r_bloomstate.bloomtextureheight;
7964 // compute a texcoord array with the specified x and y offset
7965 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7966 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7967 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7968 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7969 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7970 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7971 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7972 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7973 // this r value looks like a 'dot' particle, fading sharply to
7974 // black at the edges
7975 // (probably not realistic but looks good enough)
7976 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7977 //r = brighten/(range*2+1);
7978 r = brighten / (range * 2 + 1);
7980 r *= (1 - x*x/(float)(range*range));
7981 GL_Color(r, r, r, 1);
7982 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7983 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7984 GL_BlendFunc(GL_ONE, GL_ONE);
7987 // copy the vertically blurred bloom view to a texture
7988 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);
7989 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7992 // apply subtract last
7993 // (just like it would be in a GLSL shader)
7994 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7996 GL_BlendFunc(GL_ONE, GL_ZERO);
7997 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7998 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7999 GL_Color(1, 1, 1, 1);
8000 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8001 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8003 GL_BlendFunc(GL_ONE, GL_ONE);
8004 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
8005 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8006 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8007 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
8008 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8009 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8010 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
8012 // copy the darkened bloom view to a texture
8013 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);
8014 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8018 void R_HDR_RenderBloomTexture(void)
8020 int oldwidth, oldheight;
8021 float oldcolorscale;
8023 oldcolorscale = r_refdef.view.colorscale;
8024 oldwidth = r_refdef.view.width;
8025 oldheight = r_refdef.view.height;
8026 r_refdef.view.width = r_bloomstate.bloomwidth;
8027 r_refdef.view.height = r_bloomstate.bloomheight;
8029 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
8030 // TODO: add exposure compensation features
8031 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8033 r_refdef.view.showdebug = false;
8034 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8036 R_ResetViewRendering3D();
8038 R_ClearScreen(r_refdef.fogenabled);
8039 if (r_timereport_active)
8040 R_TimeReport("HDRclear");
8043 if (r_timereport_active)
8044 R_TimeReport("visibility");
8046 // only do secondary renders with HDR if r_hdr is 2 or higher
8047 r_waterstate.numwaterplanes = 0;
8048 if (r_waterstate.enabled && r_hdr.integer >= 2)
8049 R_RenderWaterPlanes();
8051 r_refdef.view.showdebug = true;
8053 r_waterstate.numwaterplanes = 0;
8055 R_ResetViewRendering2D();
8057 R_Bloom_CopyHDRTexture();
8058 R_Bloom_MakeTexture();
8060 // restore the view settings
8061 r_refdef.view.width = oldwidth;
8062 r_refdef.view.height = oldheight;
8063 r_refdef.view.colorscale = oldcolorscale;
8065 R_ResetViewRendering3D();
8067 R_ClearScreen(r_refdef.fogenabled);
8068 if (r_timereport_active)
8069 R_TimeReport("viewclear");
8072 static void R_BlendView(void)
8074 unsigned int permutation;
8075 float uservecs[4][4];
8077 switch (vid.renderpath)
8079 case RENDERPATH_GL20:
8080 case RENDERPATH_CGGL:
8082 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8083 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8084 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8085 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8086 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8088 if (r_bloomstate.texture_screen)
8090 // make sure the buffer is available
8091 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8093 R_ResetViewRendering2D();
8094 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8095 R_Mesh_ColorPointer(NULL, 0, 0);
8097 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8099 // declare variables
8101 static float avgspeed;
8103 speed = VectorLength(cl.movement_velocity);
8105 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8106 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8108 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8109 speed = bound(0, speed, 1);
8110 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8112 // calculate values into a standard alpha
8113 cl.motionbluralpha = 1 - exp(-
8115 (r_motionblur.value * speed / 80)
8117 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8120 max(0.0001, cl.time - cl.oldtime) // fps independent
8123 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8124 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8126 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8128 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8129 GL_Color(1, 1, 1, cl.motionbluralpha);
8130 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8131 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8132 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8133 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8137 // copy view into the screen texture
8138 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);
8139 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8141 else if (!r_bloomstate.texture_bloom)
8143 // we may still have to do view tint...
8144 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8146 // apply a color tint to the whole view
8147 R_ResetViewRendering2D();
8148 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8149 R_Mesh_ColorPointer(NULL, 0, 0);
8150 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8151 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8152 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8153 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8155 break; // no screen processing, no bloom, skip it
8158 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8160 // render simple bloom effect
8161 // copy the screen and shrink it and darken it for the bloom process
8162 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8163 // make the bloom texture
8164 R_Bloom_MakeTexture();
8167 #if _MSC_VER >= 1400
8168 #define sscanf sscanf_s
8170 memset(uservecs, 0, sizeof(uservecs));
8171 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8172 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8173 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8174 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8176 R_ResetViewRendering2D();
8177 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8178 R_Mesh_ColorPointer(NULL, 0, 0);
8179 GL_Color(1, 1, 1, 1);
8180 GL_BlendFunc(GL_ONE, GL_ZERO);
8181 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8182 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8184 switch(vid.renderpath)
8186 case RENDERPATH_GL20:
8187 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8188 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8189 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8190 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8191 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]);
8192 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8193 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]);
8194 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]);
8195 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]);
8196 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]);
8197 // if (r_glsl_permutation->loc_UseSobel >= 0) qglUniform1fARB(r_glsl_permutation->loc_UseSobel , r_glsl_postprocess_sobel.value);
8198 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
8199 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8201 case RENDERPATH_CGGL:
8203 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
8204 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
8205 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
8206 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
8207 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
8208 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
8209 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
8210 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
8211 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
8212 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
8213 // if (r_cg_permutation->fp_UseSobel ) cgGLSetParameter1f( r_cg_permutation->fp_UseSobel , r_glsl_postprocess_sobel.value);CHECKCGERROR
8214 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
8215 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
8221 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8222 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8224 case RENDERPATH_GL13:
8225 case RENDERPATH_GL11:
8226 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8228 // apply a color tint to the whole view
8229 R_ResetViewRendering2D();
8230 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8231 R_Mesh_ColorPointer(NULL, 0, 0);
8232 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8233 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8234 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8235 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8241 matrix4x4_t r_waterscrollmatrix;
8243 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8245 if (r_refdef.fog_density)
8247 r_refdef.fogcolor[0] = r_refdef.fog_red;
8248 r_refdef.fogcolor[1] = r_refdef.fog_green;
8249 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8251 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8252 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8253 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8254 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8258 VectorCopy(r_refdef.fogcolor, fogvec);
8259 // color.rgb *= ContrastBoost * SceneBrightness;
8260 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8261 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8262 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8263 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8268 void R_UpdateVariables(void)
8272 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8274 r_refdef.farclip = r_farclip_base.value;
8275 if (r_refdef.scene.worldmodel)
8276 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8277 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8279 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8280 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8281 r_refdef.polygonfactor = 0;
8282 r_refdef.polygonoffset = 0;
8283 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8284 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8286 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8287 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8288 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8289 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8290 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8291 if (r_showsurfaces.integer)
8293 r_refdef.scene.rtworld = false;
8294 r_refdef.scene.rtworldshadows = false;
8295 r_refdef.scene.rtdlight = false;
8296 r_refdef.scene.rtdlightshadows = false;
8297 r_refdef.lightmapintensity = 0;
8300 if (gamemode == GAME_NEHAHRA)
8302 if (gl_fogenable.integer)
8304 r_refdef.oldgl_fogenable = true;
8305 r_refdef.fog_density = gl_fogdensity.value;
8306 r_refdef.fog_red = gl_fogred.value;
8307 r_refdef.fog_green = gl_foggreen.value;
8308 r_refdef.fog_blue = gl_fogblue.value;
8309 r_refdef.fog_alpha = 1;
8310 r_refdef.fog_start = 0;
8311 r_refdef.fog_end = gl_skyclip.value;
8312 r_refdef.fog_height = 1<<30;
8313 r_refdef.fog_fadedepth = 128;
8315 else if (r_refdef.oldgl_fogenable)
8317 r_refdef.oldgl_fogenable = false;
8318 r_refdef.fog_density = 0;
8319 r_refdef.fog_red = 0;
8320 r_refdef.fog_green = 0;
8321 r_refdef.fog_blue = 0;
8322 r_refdef.fog_alpha = 0;
8323 r_refdef.fog_start = 0;
8324 r_refdef.fog_end = 0;
8325 r_refdef.fog_height = 1<<30;
8326 r_refdef.fog_fadedepth = 128;
8330 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8331 r_refdef.fog_start = max(0, r_refdef.fog_start);
8332 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8334 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8336 if (r_refdef.fog_density && r_drawfog.integer)
8338 r_refdef.fogenabled = true;
8339 // this is the point where the fog reaches 0.9986 alpha, which we
8340 // consider a good enough cutoff point for the texture
8341 // (0.9986 * 256 == 255.6)
8342 if (r_fog_exp2.integer)
8343 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8345 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8346 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8347 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8348 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8349 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
8350 R_BuildFogHeightTexture();
8351 // fog color was already set
8352 // update the fog texture
8353 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)
8354 R_BuildFogTexture();
8355 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
8356 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
8359 r_refdef.fogenabled = false;
8361 switch(vid.renderpath)
8363 case RENDERPATH_GL20:
8364 case RENDERPATH_CGGL:
8365 if(v_glslgamma.integer && !vid_gammatables_trivial)
8367 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8369 // build GLSL gamma texture
8370 #define RAMPWIDTH 256
8371 unsigned short ramp[RAMPWIDTH * 3];
8372 unsigned char rampbgr[RAMPWIDTH][4];
8375 r_texture_gammaramps_serial = vid_gammatables_serial;
8377 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8378 for(i = 0; i < RAMPWIDTH; ++i)
8380 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8381 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8382 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8385 if (r_texture_gammaramps)
8387 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8391 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);
8397 // remove GLSL gamma texture
8400 case RENDERPATH_GL13:
8401 case RENDERPATH_GL11:
8406 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8407 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8413 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8414 if( scenetype != r_currentscenetype ) {
8415 // store the old scenetype
8416 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8417 r_currentscenetype = scenetype;
8418 // move in the new scene
8419 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8428 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8430 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8431 if( scenetype == r_currentscenetype ) {
8432 return &r_refdef.scene;
8434 return &r_scenes_store[ scenetype ];
8443 void R_RenderView(void)
8445 if (r_timereport_active)
8446 R_TimeReport("start");
8447 r_textureframe++; // used only by R_GetCurrentTexture
8448 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8450 if (!r_drawentities.integer)
8451 r_refdef.scene.numentities = 0;
8453 R_AnimCache_ClearCache();
8454 R_FrameData_NewFrame();
8456 if (r_refdef.view.isoverlay)
8458 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8459 GL_Clear( GL_DEPTH_BUFFER_BIT );
8460 R_TimeReport("depthclear");
8462 r_refdef.view.showdebug = false;
8464 r_waterstate.enabled = false;
8465 r_waterstate.numwaterplanes = 0;
8473 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
8474 return; //Host_Error ("R_RenderView: NULL worldmodel");
8476 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8478 R_RenderView_UpdateViewVectors();
8480 R_Shadow_UpdateWorldLightSelection();
8482 R_Bloom_StartFrame();
8483 R_Water_StartFrame();
8486 if (r_timereport_active)
8487 R_TimeReport("viewsetup");
8489 R_ResetViewRendering3D();
8491 if (r_refdef.view.clear || r_refdef.fogenabled)
8493 R_ClearScreen(r_refdef.fogenabled);
8494 if (r_timereport_active)
8495 R_TimeReport("viewclear");
8497 r_refdef.view.clear = true;
8499 // this produces a bloom texture to be used in R_BlendView() later
8500 if (r_hdr.integer && r_bloomstate.bloomwidth)
8502 R_HDR_RenderBloomTexture();
8503 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8504 r_textureframe++; // used only by R_GetCurrentTexture
8507 r_refdef.view.showdebug = true;
8510 if (r_timereport_active)
8511 R_TimeReport("visibility");
8513 r_waterstate.numwaterplanes = 0;
8514 if (r_waterstate.enabled)
8515 R_RenderWaterPlanes();
8518 r_waterstate.numwaterplanes = 0;
8521 if (r_timereport_active)
8522 R_TimeReport("blendview");
8524 GL_Scissor(0, 0, vid.width, vid.height);
8525 GL_ScissorTest(false);
8529 void R_RenderWaterPlanes(void)
8531 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8533 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8534 if (r_timereport_active)
8535 R_TimeReport("waterworld");
8538 // don't let sound skip if going slow
8539 if (r_refdef.scene.extraupdate)
8542 R_DrawModelsAddWaterPlanes();
8543 if (r_timereport_active)
8544 R_TimeReport("watermodels");
8546 if (r_waterstate.numwaterplanes)
8548 R_Water_ProcessPlanes();
8549 if (r_timereport_active)
8550 R_TimeReport("waterscenes");
8554 extern void R_DrawLightningBeams (void);
8555 extern void VM_CL_AddPolygonsToMeshQueue (void);
8556 extern void R_DrawPortals (void);
8557 extern cvar_t cl_locs_show;
8558 static void R_DrawLocs(void);
8559 static void R_DrawEntityBBoxes(void);
8560 static void R_DrawModelDecals(void);
8561 extern void R_DrawModelShadows(void);
8562 extern void R_DrawModelShadowMaps(void);
8563 extern cvar_t cl_decals_newsystem;
8564 extern qboolean r_shadow_usingdeferredprepass;
8565 void R_RenderScene(void)
8567 qboolean shadowmapping = false;
8569 if (r_timereport_active)
8570 R_TimeReport("beginscene");
8572 r_refdef.stats.renders++;
8576 // don't let sound skip if going slow
8577 if (r_refdef.scene.extraupdate)
8580 R_MeshQueue_BeginScene();
8584 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);
8586 if (r_timereport_active)
8587 R_TimeReport("skystartframe");
8589 if (cl.csqc_vidvars.drawworld)
8591 // don't let sound skip if going slow
8592 if (r_refdef.scene.extraupdate)
8595 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8597 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8598 if (r_timereport_active)
8599 R_TimeReport("worldsky");
8602 if (R_DrawBrushModelsSky() && r_timereport_active)
8603 R_TimeReport("bmodelsky");
8605 if (skyrendermasked && skyrenderlater)
8607 // we have to force off the water clipping plane while rendering sky
8611 if (r_timereport_active)
8612 R_TimeReport("sky");
8616 R_AnimCache_CacheVisibleEntities();
8617 if (r_timereport_active)
8618 R_TimeReport("animation");
8620 R_Shadow_PrepareLights();
8621 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8622 R_Shadow_PrepareModelShadows();
8623 if (r_timereport_active)
8624 R_TimeReport("preparelights");
8626 if (R_Shadow_ShadowMappingEnabled())
8627 shadowmapping = true;
8629 if (r_shadow_usingdeferredprepass)
8630 R_Shadow_DrawPrepass();
8632 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8634 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8635 if (r_timereport_active)
8636 R_TimeReport("worlddepth");
8638 if (r_depthfirst.integer >= 2)
8640 R_DrawModelsDepth();
8641 if (r_timereport_active)
8642 R_TimeReport("modeldepth");
8645 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
8647 R_DrawModelShadowMaps();
8648 R_ResetViewRendering3D();
8649 // don't let sound skip if going slow
8650 if (r_refdef.scene.extraupdate)
8654 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8656 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8657 if (r_timereport_active)
8658 R_TimeReport("world");
8661 // don't let sound skip if going slow
8662 if (r_refdef.scene.extraupdate)
8666 if (r_timereport_active)
8667 R_TimeReport("models");
8669 // don't let sound skip if going slow
8670 if (r_refdef.scene.extraupdate)
8673 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8675 R_DrawModelShadows();
8676 R_ResetViewRendering3D();
8677 // don't let sound skip if going slow
8678 if (r_refdef.scene.extraupdate)
8682 if (!r_shadow_usingdeferredprepass)
8684 R_Shadow_DrawLights();
8685 if (r_timereport_active)
8686 R_TimeReport("rtlights");
8689 // don't let sound skip if going slow
8690 if (r_refdef.scene.extraupdate)
8693 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8695 R_DrawModelShadows();
8696 R_ResetViewRendering3D();
8697 // don't let sound skip if going slow
8698 if (r_refdef.scene.extraupdate)
8702 if (cl.csqc_vidvars.drawworld)
8704 if (cl_decals_newsystem.integer)
8706 R_DrawModelDecals();
8707 if (r_timereport_active)
8708 R_TimeReport("modeldecals");
8713 if (r_timereport_active)
8714 R_TimeReport("decals");
8718 if (r_timereport_active)
8719 R_TimeReport("particles");
8722 if (r_timereport_active)
8723 R_TimeReport("explosions");
8725 R_DrawLightningBeams();
8726 if (r_timereport_active)
8727 R_TimeReport("lightning");
8730 VM_CL_AddPolygonsToMeshQueue();
8732 if (r_refdef.view.showdebug)
8734 if (cl_locs_show.integer)
8737 if (r_timereport_active)
8738 R_TimeReport("showlocs");
8741 if (r_drawportals.integer)
8744 if (r_timereport_active)
8745 R_TimeReport("portals");
8748 if (r_showbboxes.value > 0)
8750 R_DrawEntityBBoxes();
8751 if (r_timereport_active)
8752 R_TimeReport("bboxes");
8756 R_MeshQueue_RenderTransparent();
8757 if (r_timereport_active)
8758 R_TimeReport("drawtrans");
8760 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))
8762 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8763 if (r_timereport_active)
8764 R_TimeReport("worlddebug");
8765 R_DrawModelsDebug();
8766 if (r_timereport_active)
8767 R_TimeReport("modeldebug");
8770 if (cl.csqc_vidvars.drawworld)
8772 R_Shadow_DrawCoronas();
8773 if (r_timereport_active)
8774 R_TimeReport("coronas");
8777 // don't let sound skip if going slow
8778 if (r_refdef.scene.extraupdate)
8781 R_ResetViewRendering2D();
8784 static const unsigned short bboxelements[36] =
8794 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8797 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8799 RSurf_ActiveWorldEntity();
8801 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8802 GL_DepthMask(false);
8803 GL_DepthRange(0, 1);
8804 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8805 R_Mesh_ResetTextureState();
8807 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8808 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8809 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8810 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8811 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8812 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8813 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8814 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8815 R_FillColors(color4f, 8, cr, cg, cb, ca);
8816 if (r_refdef.fogenabled)
8818 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8820 f1 = RSurf_FogVertex(v);
8822 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8823 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8824 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8827 R_Mesh_VertexPointer(vertex3f, 0, 0);
8828 R_Mesh_ColorPointer(color4f, 0, 0);
8829 R_Mesh_ResetTextureState();
8830 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8831 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8834 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8838 prvm_edict_t *edict;
8839 prvm_prog_t *prog_save = prog;
8841 // this function draws bounding boxes of server entities
8845 GL_CullFace(GL_NONE);
8846 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8850 for (i = 0;i < numsurfaces;i++)
8852 edict = PRVM_EDICT_NUM(surfacelist[i]);
8853 switch ((int)edict->fields.server->solid)
8855 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
8856 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
8857 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
8858 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8859 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
8860 default: Vector4Set(color, 0, 0, 0, 0.50);break;
8862 color[3] *= r_showbboxes.value;
8863 color[3] = bound(0, color[3], 1);
8864 GL_DepthTest(!r_showdisabledepthtest.integer);
8865 GL_CullFace(r_refdef.view.cullface_front);
8866 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8872 static void R_DrawEntityBBoxes(void)
8875 prvm_edict_t *edict;
8877 prvm_prog_t *prog_save = prog;
8879 // this function draws bounding boxes of server entities
8885 for (i = 0;i < prog->num_edicts;i++)
8887 edict = PRVM_EDICT_NUM(i);
8888 if (edict->priv.server->free)
8890 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8891 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8893 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8895 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8896 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8902 static const int nomodelelement3i[24] =
8914 static const unsigned short nomodelelement3s[24] =
8926 static const float nomodelvertex3f[6*3] =
8936 static const float nomodelcolor4f[6*4] =
8938 0.0f, 0.0f, 0.5f, 1.0f,
8939 0.0f, 0.0f, 0.5f, 1.0f,
8940 0.0f, 0.5f, 0.0f, 1.0f,
8941 0.0f, 0.5f, 0.0f, 1.0f,
8942 0.5f, 0.0f, 0.0f, 1.0f,
8943 0.5f, 0.0f, 0.0f, 1.0f
8946 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8952 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);
8954 // this is only called once per entity so numsurfaces is always 1, and
8955 // surfacelist is always {0}, so this code does not handle batches
8957 if (rsurface.ent_flags & RENDER_ADDITIVE)
8959 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8960 GL_DepthMask(false);
8962 else if (rsurface.colormod[3] < 1)
8964 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8965 GL_DepthMask(false);
8969 GL_BlendFunc(GL_ONE, GL_ZERO);
8972 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8973 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8974 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8975 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8976 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8977 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8978 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8979 R_Mesh_ColorPointer(color4f, 0, 0);
8980 for (i = 0, c = color4f;i < 6;i++, c += 4)
8982 c[0] *= rsurface.colormod[0];
8983 c[1] *= rsurface.colormod[1];
8984 c[2] *= rsurface.colormod[2];
8985 c[3] *= rsurface.colormod[3];
8987 if (r_refdef.fogenabled)
8989 for (i = 0, c = color4f;i < 6;i++, c += 4)
8991 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8993 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8994 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8995 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8998 R_Mesh_ResetTextureState();
8999 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
9002 void R_DrawNoModel(entity_render_t *ent)
9005 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9006 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9007 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9009 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9012 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9014 vec3_t right1, right2, diff, normal;
9016 VectorSubtract (org2, org1, normal);
9018 // calculate 'right' vector for start
9019 VectorSubtract (r_refdef.view.origin, org1, diff);
9020 CrossProduct (normal, diff, right1);
9021 VectorNormalize (right1);
9023 // calculate 'right' vector for end
9024 VectorSubtract (r_refdef.view.origin, org2, diff);
9025 CrossProduct (normal, diff, right2);
9026 VectorNormalize (right2);
9028 vert[ 0] = org1[0] + width * right1[0];
9029 vert[ 1] = org1[1] + width * right1[1];
9030 vert[ 2] = org1[2] + width * right1[2];
9031 vert[ 3] = org1[0] - width * right1[0];
9032 vert[ 4] = org1[1] - width * right1[1];
9033 vert[ 5] = org1[2] - width * right1[2];
9034 vert[ 6] = org2[0] - width * right2[0];
9035 vert[ 7] = org2[1] - width * right2[1];
9036 vert[ 8] = org2[2] - width * right2[2];
9037 vert[ 9] = org2[0] + width * right2[0];
9038 vert[10] = org2[1] + width * right2[1];
9039 vert[11] = org2[2] + width * right2[2];
9042 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)
9044 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9045 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9046 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9047 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9048 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9049 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9050 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9051 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9052 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9053 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9054 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9055 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9058 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9063 VectorSet(v, x, y, z);
9064 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9065 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9067 if (i == mesh->numvertices)
9069 if (mesh->numvertices < mesh->maxvertices)
9071 VectorCopy(v, vertex3f);
9072 mesh->numvertices++;
9074 return mesh->numvertices;
9080 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9084 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9085 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9086 e = mesh->element3i + mesh->numtriangles * 3;
9087 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9089 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9090 if (mesh->numtriangles < mesh->maxtriangles)
9095 mesh->numtriangles++;
9097 element[1] = element[2];
9101 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9105 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9106 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9107 e = mesh->element3i + mesh->numtriangles * 3;
9108 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9110 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9111 if (mesh->numtriangles < mesh->maxtriangles)
9116 mesh->numtriangles++;
9118 element[1] = element[2];
9122 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9123 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9125 int planenum, planenum2;
9128 mplane_t *plane, *plane2;
9130 double temppoints[2][256*3];
9131 // figure out how large a bounding box we need to properly compute this brush
9133 for (w = 0;w < numplanes;w++)
9134 maxdist = max(maxdist, fabs(planes[w].dist));
9135 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9136 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9137 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9141 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9142 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9144 if (planenum2 == planenum)
9146 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);
9149 if (tempnumpoints < 3)
9151 // generate elements forming a triangle fan for this polygon
9152 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9156 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)
9158 texturelayer_t *layer;
9159 layer = t->currentlayers + t->currentnumlayers++;
9161 layer->depthmask = depthmask;
9162 layer->blendfunc1 = blendfunc1;
9163 layer->blendfunc2 = blendfunc2;
9164 layer->texture = texture;
9165 layer->texmatrix = *matrix;
9166 layer->color[0] = r;
9167 layer->color[1] = g;
9168 layer->color[2] = b;
9169 layer->color[3] = a;
9172 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9175 index = parms[2] + r_refdef.scene.time * parms[3];
9176 index -= floor(index);
9180 case Q3WAVEFUNC_NONE:
9181 case Q3WAVEFUNC_NOISE:
9182 case Q3WAVEFUNC_COUNT:
9185 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9186 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9187 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9188 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9189 case Q3WAVEFUNC_TRIANGLE:
9191 f = index - floor(index);
9202 return (float)(parms[0] + parms[1] * f);
9205 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9210 matrix4x4_t matrix, temp;
9211 switch(tcmod->tcmod)
9215 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9216 matrix = r_waterscrollmatrix;
9218 matrix = identitymatrix;
9220 case Q3TCMOD_ENTITYTRANSLATE:
9221 // this is used in Q3 to allow the gamecode to control texcoord
9222 // scrolling on the entity, which is not supported in darkplaces yet.
9223 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9225 case Q3TCMOD_ROTATE:
9226 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9227 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9228 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9231 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9233 case Q3TCMOD_SCROLL:
9234 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9236 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9237 w = (int) tcmod->parms[0];
9238 h = (int) tcmod->parms[1];
9239 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9241 idx = (int) floor(f * w * h);
9242 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9244 case Q3TCMOD_STRETCH:
9245 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9246 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9248 case Q3TCMOD_TRANSFORM:
9249 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
9250 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
9251 VectorSet(tcmat + 6, 0 , 0 , 1);
9252 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
9253 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9255 case Q3TCMOD_TURBULENT:
9256 // this is handled in the RSurf_PrepareVertices function
9257 matrix = identitymatrix;
9261 Matrix4x4_Concat(texmatrix, &matrix, &temp);
9264 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9266 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9267 char name[MAX_QPATH];
9268 skinframe_t *skinframe;
9269 unsigned char pixels[296*194];
9270 strlcpy(cache->name, skinname, sizeof(cache->name));
9271 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9272 if (developer_loading.integer)
9273 Con_Printf("loading %s\n", name);
9274 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9275 if (!skinframe || !skinframe->base)
9278 fs_offset_t filesize;
9280 f = FS_LoadFile(name, tempmempool, true, &filesize);
9283 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9284 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9288 cache->skinframe = skinframe;
9291 texture_t *R_GetCurrentTexture(texture_t *t)
9294 const entity_render_t *ent = rsurface.entity;
9295 dp_model_t *model = ent->model;
9296 q3shaderinfo_layer_tcmod_t *tcmod;
9298 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9299 return t->currentframe;
9300 t->update_lastrenderframe = r_textureframe;
9301 t->update_lastrenderentity = (void *)ent;
9303 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
9304 t->camera_entity = ent->entitynumber;
9306 t->camera_entity = 0;
9308 // switch to an alternate material if this is a q1bsp animated material
9310 texture_t *texture = t;
9311 int s = rsurface.ent_skinnum;
9312 if ((unsigned int)s >= (unsigned int)model->numskins)
9314 if (model->skinscenes)
9316 if (model->skinscenes[s].framecount > 1)
9317 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9319 s = model->skinscenes[s].firstframe;
9322 t = t + s * model->num_surfaces;
9325 // use an alternate animation if the entity's frame is not 0,
9326 // and only if the texture has an alternate animation
9327 if (rsurface.ent_alttextures && t->anim_total[1])
9328 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9330 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9332 texture->currentframe = t;
9335 // update currentskinframe to be a qw skin or animation frame
9336 if (rsurface.ent_qwskin >= 0)
9338 i = rsurface.ent_qwskin;
9339 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9341 r_qwskincache_size = cl.maxclients;
9343 Mem_Free(r_qwskincache);
9344 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9346 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9347 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9348 t->currentskinframe = r_qwskincache[i].skinframe;
9349 if (t->currentskinframe == NULL)
9350 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9352 else if (t->numskinframes >= 2)
9353 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9354 if (t->backgroundnumskinframes >= 2)
9355 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9357 t->currentmaterialflags = t->basematerialflags;
9358 t->currentalpha = rsurface.colormod[3];
9359 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9360 t->currentalpha *= r_wateralpha.value;
9361 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9362 t->currentalpha *= t->r_water_wateralpha;
9363 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9364 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
9365 if (!(rsurface.ent_flags & RENDER_LIGHT))
9366 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9367 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9369 // pick a model lighting mode
9370 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9371 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9373 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9375 if (rsurface.ent_flags & RENDER_ADDITIVE)
9376 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9377 else if (t->currentalpha < 1)
9378 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9379 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9380 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9381 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9382 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9383 if (t->backgroundnumskinframes)
9384 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9385 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9387 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
9388 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9391 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
9392 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9393 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9395 // there is no tcmod
9396 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9398 t->currenttexmatrix = r_waterscrollmatrix;
9399 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9401 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9403 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9404 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9407 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9408 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9409 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9410 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9412 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9413 if (t->currentskinframe->qpixels)
9414 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9415 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9416 if (!t->basetexture)
9417 t->basetexture = r_texture_notexture;
9418 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9419 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9420 t->nmaptexture = t->currentskinframe->nmap;
9421 if (!t->nmaptexture)
9422 t->nmaptexture = r_texture_blanknormalmap;
9423 t->glosstexture = r_texture_black;
9424 t->glowtexture = t->currentskinframe->glow;
9425 t->fogtexture = t->currentskinframe->fog;
9426 t->reflectmasktexture = t->currentskinframe->reflect;
9427 if (t->backgroundnumskinframes)
9429 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9430 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9431 t->backgroundglosstexture = r_texture_black;
9432 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9433 if (!t->backgroundnmaptexture)
9434 t->backgroundnmaptexture = r_texture_blanknormalmap;
9438 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9439 t->backgroundnmaptexture = r_texture_blanknormalmap;
9440 t->backgroundglosstexture = r_texture_black;
9441 t->backgroundglowtexture = NULL;
9443 t->specularpower = r_shadow_glossexponent.value;
9444 // TODO: store reference values for these in the texture?
9445 t->specularscale = 0;
9446 if (r_shadow_gloss.integer > 0)
9448 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9450 if (r_shadow_glossintensity.value > 0)
9452 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9453 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9454 t->specularscale = r_shadow_glossintensity.value;
9457 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9459 t->glosstexture = r_texture_white;
9460 t->backgroundglosstexture = r_texture_white;
9461 t->specularscale = r_shadow_gloss2intensity.value;
9462 t->specularpower = r_shadow_gloss2exponent.value;
9465 t->specularscale *= t->specularscalemod;
9466 t->specularpower *= t->specularpowermod;
9468 // lightmaps mode looks bad with dlights using actual texturing, so turn
9469 // off the colormap and glossmap, but leave the normalmap on as it still
9470 // accurately represents the shading involved
9471 if (gl_lightmaps.integer)
9473 t->basetexture = r_texture_grey128;
9474 t->pantstexture = r_texture_black;
9475 t->shirttexture = r_texture_black;
9476 t->nmaptexture = r_texture_blanknormalmap;
9477 t->glosstexture = r_texture_black;
9478 t->glowtexture = NULL;
9479 t->fogtexture = NULL;
9480 t->reflectmasktexture = NULL;
9481 t->backgroundbasetexture = NULL;
9482 t->backgroundnmaptexture = r_texture_blanknormalmap;
9483 t->backgroundglosstexture = r_texture_black;
9484 t->backgroundglowtexture = NULL;
9485 t->specularscale = 0;
9486 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9489 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9490 VectorClear(t->dlightcolor);
9491 t->currentnumlayers = 0;
9492 if (t->currentmaterialflags & MATERIALFLAG_WALL)
9494 int blendfunc1, blendfunc2;
9496 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9498 blendfunc1 = GL_SRC_ALPHA;
9499 blendfunc2 = GL_ONE;
9501 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9503 blendfunc1 = GL_SRC_ALPHA;
9504 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9506 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9508 blendfunc1 = t->customblendfunc[0];
9509 blendfunc2 = t->customblendfunc[1];
9513 blendfunc1 = GL_ONE;
9514 blendfunc2 = GL_ZERO;
9516 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9517 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9519 // fullbright is not affected by r_refdef.lightmapintensity
9520 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]);
9521 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9522 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]);
9523 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9524 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]);
9528 vec3_t ambientcolor;
9530 // set the color tint used for lights affecting this surface
9531 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9533 // q3bsp has no lightmap updates, so the lightstylevalue that
9534 // would normally be baked into the lightmap must be
9535 // applied to the color
9536 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9537 if (model->type == mod_brushq3)
9538 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9539 colorscale *= r_refdef.lightmapintensity;
9540 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9541 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9542 // basic lit geometry
9543 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]);
9544 // add pants/shirt if needed
9545 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9546 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]);
9547 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9548 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]);
9549 // now add ambient passes if needed
9550 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9552 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]);
9553 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9554 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]);
9555 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9556 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]);
9559 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9560 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]);
9561 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9563 // if this is opaque use alpha blend which will darken the earlier
9566 // if this is an alpha blended material, all the earlier passes
9567 // were darkened by fog already, so we only need to add the fog
9568 // color ontop through the fog mask texture
9570 // if this is an additive blended material, all the earlier passes
9571 // were darkened by fog already, and we should not add fog color
9572 // (because the background was not darkened, there is no fog color
9573 // that was lost behind it).
9574 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]);
9578 return t->currentframe;
9581 rsurfacestate_t rsurface;
9583 void R_Mesh_ResizeArrays(int newvertices)
9586 if (rsurface.array_size >= newvertices)
9588 if (rsurface.array_modelvertex3f)
9589 Mem_Free(rsurface.array_modelvertex3f);
9590 rsurface.array_size = (newvertices + 1023) & ~1023;
9591 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9592 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
9593 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
9594 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
9595 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
9596 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
9597 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9598 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9599 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
9600 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
9601 rsurface.array_color4f = base + rsurface.array_size * 27;
9602 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9605 void RSurf_ActiveWorldEntity(void)
9607 dp_model_t *model = r_refdef.scene.worldmodel;
9608 //if (rsurface.entity == r_refdef.scene.worldentity)
9610 rsurface.entity = r_refdef.scene.worldentity;
9611 rsurface.skeleton = NULL;
9612 rsurface.ent_skinnum = 0;
9613 rsurface.ent_qwskin = -1;
9614 rsurface.ent_shadertime = 0;
9615 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9616 if (rsurface.array_size < model->surfmesh.num_vertices)
9617 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9618 rsurface.matrix = identitymatrix;
9619 rsurface.inversematrix = identitymatrix;
9620 rsurface.matrixscale = 1;
9621 rsurface.inversematrixscale = 1;
9622 R_EntityMatrix(&identitymatrix);
9623 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9624 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9625 rsurface.fograngerecip = r_refdef.fograngerecip;
9626 rsurface.fogheightfade = r_refdef.fogheightfade;
9627 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9628 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9629 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9630 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9631 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9632 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9633 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9634 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9635 rsurface.colormod[3] = 1;
9636 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);
9637 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9638 rsurface.frameblend[0].lerp = 1;
9639 rsurface.ent_alttextures = false;
9640 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9641 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9642 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9643 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9644 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9645 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9646 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9647 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9648 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9649 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9650 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9651 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9652 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9653 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9654 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9655 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9656 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9657 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9658 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9659 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9660 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9661 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9662 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9663 rsurface.modelelement3i = model->surfmesh.data_element3i;
9664 rsurface.modelelement3s = model->surfmesh.data_element3s;
9665 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9666 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9667 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9668 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9669 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9670 rsurface.modelsurfaces = model->data_surfaces;
9671 rsurface.generatedvertex = false;
9672 rsurface.vertex3f = rsurface.modelvertex3f;
9673 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9674 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9675 rsurface.svector3f = rsurface.modelsvector3f;
9676 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9677 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9678 rsurface.tvector3f = rsurface.modeltvector3f;
9679 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9680 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9681 rsurface.normal3f = rsurface.modelnormal3f;
9682 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9683 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9684 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9687 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9689 dp_model_t *model = ent->model;
9690 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9692 rsurface.entity = (entity_render_t *)ent;
9693 rsurface.skeleton = ent->skeleton;
9694 rsurface.ent_skinnum = ent->skinnum;
9695 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;
9696 rsurface.ent_shadertime = ent->shadertime;
9697 rsurface.ent_flags = ent->flags;
9698 if (rsurface.array_size < model->surfmesh.num_vertices)
9699 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9700 rsurface.matrix = ent->matrix;
9701 rsurface.inversematrix = ent->inversematrix;
9702 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9703 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9704 R_EntityMatrix(&rsurface.matrix);
9705 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9706 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9707 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9708 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9709 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9710 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9711 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9712 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9713 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9714 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9715 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9716 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9717 rsurface.colormod[3] = ent->alpha;
9718 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9719 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9720 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9721 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9722 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9723 if (ent->model->brush.submodel && !prepass)
9725 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9726 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9728 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9730 if (ent->animcache_vertex3f && !r_framedata_failed)
9732 rsurface.modelvertex3f = ent->animcache_vertex3f;
9733 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9734 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9735 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9737 else if (wanttangents)
9739 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9740 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9741 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9742 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9743 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9745 else if (wantnormals)
9747 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9748 rsurface.modelsvector3f = NULL;
9749 rsurface.modeltvector3f = NULL;
9750 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9751 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9755 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9756 rsurface.modelsvector3f = NULL;
9757 rsurface.modeltvector3f = NULL;
9758 rsurface.modelnormal3f = NULL;
9759 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9761 rsurface.modelvertex3f_bufferobject = 0;
9762 rsurface.modelvertex3f_bufferoffset = 0;
9763 rsurface.modelsvector3f_bufferobject = 0;
9764 rsurface.modelsvector3f_bufferoffset = 0;
9765 rsurface.modeltvector3f_bufferobject = 0;
9766 rsurface.modeltvector3f_bufferoffset = 0;
9767 rsurface.modelnormal3f_bufferobject = 0;
9768 rsurface.modelnormal3f_bufferoffset = 0;
9769 rsurface.generatedvertex = true;
9773 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9774 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9775 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9776 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9777 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9778 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9779 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9780 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9781 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9782 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9783 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9784 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9785 rsurface.generatedvertex = false;
9787 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9788 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9789 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9790 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9791 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9792 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9793 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9794 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9795 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9796 rsurface.modelelement3i = model->surfmesh.data_element3i;
9797 rsurface.modelelement3s = model->surfmesh.data_element3s;
9798 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9799 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9800 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9801 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9802 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9803 rsurface.modelsurfaces = model->data_surfaces;
9804 rsurface.vertex3f = rsurface.modelvertex3f;
9805 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9806 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9807 rsurface.svector3f = rsurface.modelsvector3f;
9808 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9809 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9810 rsurface.tvector3f = rsurface.modeltvector3f;
9811 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9812 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9813 rsurface.normal3f = rsurface.modelnormal3f;
9814 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9815 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9816 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9819 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)
9821 rsurface.entity = r_refdef.scene.worldentity;
9822 rsurface.skeleton = NULL;
9823 rsurface.ent_skinnum = 0;
9824 rsurface.ent_qwskin = -1;
9825 rsurface.ent_shadertime = shadertime;
9826 rsurface.ent_flags = entflags;
9827 rsurface.modelnum_vertices = numvertices;
9828 rsurface.modelnum_triangles = numtriangles;
9829 if (rsurface.array_size < rsurface.modelnum_vertices)
9830 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9831 rsurface.matrix = *matrix;
9832 rsurface.inversematrix = *inversematrix;
9833 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9834 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9835 R_EntityMatrix(&rsurface.matrix);
9836 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9837 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9838 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9839 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9840 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9841 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9842 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9843 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9844 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9845 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9846 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9847 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9848 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);
9849 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9850 rsurface.frameblend[0].lerp = 1;
9851 rsurface.ent_alttextures = false;
9852 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9853 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9856 rsurface.modelvertex3f = vertex3f;
9857 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9858 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9859 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9861 else if (wantnormals)
9863 rsurface.modelvertex3f = vertex3f;
9864 rsurface.modelsvector3f = NULL;
9865 rsurface.modeltvector3f = NULL;
9866 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9870 rsurface.modelvertex3f = vertex3f;
9871 rsurface.modelsvector3f = NULL;
9872 rsurface.modeltvector3f = NULL;
9873 rsurface.modelnormal3f = NULL;
9875 rsurface.modelvertex3f_bufferobject = 0;
9876 rsurface.modelvertex3f_bufferoffset = 0;
9877 rsurface.modelsvector3f_bufferobject = 0;
9878 rsurface.modelsvector3f_bufferoffset = 0;
9879 rsurface.modeltvector3f_bufferobject = 0;
9880 rsurface.modeltvector3f_bufferoffset = 0;
9881 rsurface.modelnormal3f_bufferobject = 0;
9882 rsurface.modelnormal3f_bufferoffset = 0;
9883 rsurface.generatedvertex = true;
9884 rsurface.modellightmapcolor4f = color4f;
9885 rsurface.modellightmapcolor4f_bufferobject = 0;
9886 rsurface.modellightmapcolor4f_bufferoffset = 0;
9887 rsurface.modeltexcoordtexture2f = texcoord2f;
9888 rsurface.modeltexcoordtexture2f_bufferobject = 0;
9889 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9890 rsurface.modeltexcoordlightmap2f = NULL;
9891 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9892 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9893 rsurface.modelelement3i = element3i;
9894 rsurface.modelelement3s = element3s;
9895 rsurface.modelelement3i_bufferobject = 0;
9896 rsurface.modelelement3s_bufferobject = 0;
9897 rsurface.modellightmapoffsets = NULL;
9898 rsurface.modelsurfaces = NULL;
9899 rsurface.vertex3f = rsurface.modelvertex3f;
9900 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9901 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9902 rsurface.svector3f = rsurface.modelsvector3f;
9903 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9904 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9905 rsurface.tvector3f = rsurface.modeltvector3f;
9906 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9907 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9908 rsurface.normal3f = rsurface.modelnormal3f;
9909 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9910 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9911 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9913 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9915 if ((wantnormals || wanttangents) && !normal3f)
9916 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9917 if (wanttangents && !svector3f)
9918 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);
9922 float RSurf_FogPoint(const float *v)
9924 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9925 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9926 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9927 float FogHeightFade = r_refdef.fogheightfade;
9929 unsigned int fogmasktableindex;
9930 if (r_refdef.fogplaneviewabove)
9931 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9933 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9934 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9935 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9938 float RSurf_FogVertex(const float *v)
9940 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9941 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9942 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9943 float FogHeightFade = rsurface.fogheightfade;
9945 unsigned int fogmasktableindex;
9946 if (r_refdef.fogplaneviewabove)
9947 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9949 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9950 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9951 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9954 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9955 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9958 int texturesurfaceindex;
9963 const float *v1, *in_tc;
9965 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9967 q3shaderinfo_deform_t *deform;
9968 // 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
9969 if (rsurface.generatedvertex)
9971 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9972 generatenormals = true;
9973 for (i = 0;i < Q3MAXDEFORMS;i++)
9975 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9977 generatetangents = true;
9978 generatenormals = true;
9980 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9981 generatenormals = true;
9983 if (generatenormals && !rsurface.modelnormal3f)
9985 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9986 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9987 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9988 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9990 if (generatetangents && !rsurface.modelsvector3f)
9992 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9993 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9994 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9995 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9996 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9997 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9998 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);
10001 rsurface.vertex3f = rsurface.modelvertex3f;
10002 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10003 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10004 rsurface.svector3f = rsurface.modelsvector3f;
10005 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10006 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10007 rsurface.tvector3f = rsurface.modeltvector3f;
10008 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10009 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10010 rsurface.normal3f = rsurface.modelnormal3f;
10011 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10012 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10013 // if vertices are deformed (sprite flares and things in maps, possibly
10014 // water waves, bulges and other deformations), generate them into
10015 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
10016 // (may be static model data or generated data for an animated model, or
10017 // the previous deform pass)
10018 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10020 switch (deform->deform)
10023 case Q3DEFORM_PROJECTIONSHADOW:
10024 case Q3DEFORM_TEXT0:
10025 case Q3DEFORM_TEXT1:
10026 case Q3DEFORM_TEXT2:
10027 case Q3DEFORM_TEXT3:
10028 case Q3DEFORM_TEXT4:
10029 case Q3DEFORM_TEXT5:
10030 case Q3DEFORM_TEXT6:
10031 case Q3DEFORM_TEXT7:
10032 case Q3DEFORM_NONE:
10034 case Q3DEFORM_AUTOSPRITE:
10035 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10036 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10037 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10038 VectorNormalize(newforward);
10039 VectorNormalize(newright);
10040 VectorNormalize(newup);
10041 // make deformed versions of only the model vertices used by the specified surfaces
10042 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10044 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10045 // a single autosprite surface can contain multiple sprites...
10046 for (j = 0;j < surface->num_vertices - 3;j += 4)
10048 VectorClear(center);
10049 for (i = 0;i < 4;i++)
10050 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10051 VectorScale(center, 0.25f, center);
10052 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
10053 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
10054 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
10055 for (i = 0;i < 4;i++)
10057 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
10058 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10061 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);
10062 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);
10064 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10065 rsurface.vertex3f_bufferobject = 0;
10066 rsurface.vertex3f_bufferoffset = 0;
10067 rsurface.svector3f = rsurface.array_deformedsvector3f;
10068 rsurface.svector3f_bufferobject = 0;
10069 rsurface.svector3f_bufferoffset = 0;
10070 rsurface.tvector3f = rsurface.array_deformedtvector3f;
10071 rsurface.tvector3f_bufferobject = 0;
10072 rsurface.tvector3f_bufferoffset = 0;
10073 rsurface.normal3f = rsurface.array_deformednormal3f;
10074 rsurface.normal3f_bufferobject = 0;
10075 rsurface.normal3f_bufferoffset = 0;
10077 case Q3DEFORM_AUTOSPRITE2:
10078 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10079 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10080 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10081 VectorNormalize(newforward);
10082 VectorNormalize(newright);
10083 VectorNormalize(newup);
10084 // make deformed versions of only the model vertices used by the specified surfaces
10085 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10087 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10088 const float *v1, *v2;
10098 memset(shortest, 0, sizeof(shortest));
10099 // a single autosprite surface can contain multiple sprites...
10100 for (j = 0;j < surface->num_vertices - 3;j += 4)
10102 VectorClear(center);
10103 for (i = 0;i < 4;i++)
10104 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10105 VectorScale(center, 0.25f, center);
10106 // find the two shortest edges, then use them to define the
10107 // axis vectors for rotating around the central axis
10108 for (i = 0;i < 6;i++)
10110 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
10111 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
10113 Debug_PolygonBegin(NULL, 0);
10114 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
10115 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);
10116 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
10117 Debug_PolygonEnd();
10119 l = VectorDistance2(v1, v2);
10120 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10121 if (v1[2] != v2[2])
10122 l += (1.0f / 1024.0f);
10123 if (shortest[0].length2 > l || i == 0)
10125 shortest[1] = shortest[0];
10126 shortest[0].length2 = l;
10127 shortest[0].v1 = v1;
10128 shortest[0].v2 = v2;
10130 else if (shortest[1].length2 > l || i == 1)
10132 shortest[1].length2 = l;
10133 shortest[1].v1 = v1;
10134 shortest[1].v2 = v2;
10137 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10138 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10140 Debug_PolygonBegin(NULL, 0);
10141 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
10142 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);
10143 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
10144 Debug_PolygonEnd();
10146 // this calculates the right vector from the shortest edge
10147 // and the up vector from the edge midpoints
10148 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10149 VectorNormalize(right);
10150 VectorSubtract(end, start, up);
10151 VectorNormalize(up);
10152 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10153 VectorSubtract(rsurface.localvieworigin, center, forward);
10154 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10155 VectorNegate(forward, forward);
10156 VectorReflect(forward, 0, up, forward);
10157 VectorNormalize(forward);
10158 CrossProduct(up, forward, newright);
10159 VectorNormalize(newright);
10161 Debug_PolygonBegin(NULL, 0);
10162 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);
10163 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
10164 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
10165 Debug_PolygonEnd();
10168 Debug_PolygonBegin(NULL, 0);
10169 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
10170 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
10171 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
10172 Debug_PolygonEnd();
10174 // rotate the quad around the up axis vector, this is made
10175 // especially easy by the fact we know the quad is flat,
10176 // so we only have to subtract the center position and
10177 // measure distance along the right vector, and then
10178 // multiply that by the newright vector and add back the
10180 // we also need to subtract the old position to undo the
10181 // displacement from the center, which we do with a
10182 // DotProduct, the subtraction/addition of center is also
10183 // optimized into DotProducts here
10184 l = DotProduct(right, center);
10185 for (i = 0;i < 4;i++)
10187 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
10188 f = DotProduct(right, v1) - l;
10189 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10192 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);
10193 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);
10195 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10196 rsurface.vertex3f_bufferobject = 0;
10197 rsurface.vertex3f_bufferoffset = 0;
10198 rsurface.svector3f = rsurface.array_deformedsvector3f;
10199 rsurface.svector3f_bufferobject = 0;
10200 rsurface.svector3f_bufferoffset = 0;
10201 rsurface.tvector3f = rsurface.array_deformedtvector3f;
10202 rsurface.tvector3f_bufferobject = 0;
10203 rsurface.tvector3f_bufferoffset = 0;
10204 rsurface.normal3f = rsurface.array_deformednormal3f;
10205 rsurface.normal3f_bufferobject = 0;
10206 rsurface.normal3f_bufferoffset = 0;
10208 case Q3DEFORM_NORMAL:
10209 // deform the normals to make reflections wavey
10210 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10212 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10213 for (j = 0;j < surface->num_vertices;j++)
10216 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
10217 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
10218 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
10219 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10220 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10221 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10222 VectorNormalize(normal);
10224 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);
10226 rsurface.svector3f = rsurface.array_deformedsvector3f;
10227 rsurface.svector3f_bufferobject = 0;
10228 rsurface.svector3f_bufferoffset = 0;
10229 rsurface.tvector3f = rsurface.array_deformedtvector3f;
10230 rsurface.tvector3f_bufferobject = 0;
10231 rsurface.tvector3f_bufferoffset = 0;
10232 rsurface.normal3f = rsurface.array_deformednormal3f;
10233 rsurface.normal3f_bufferobject = 0;
10234 rsurface.normal3f_bufferoffset = 0;
10236 case Q3DEFORM_WAVE:
10237 // deform vertex array to make wavey water and flags and such
10238 waveparms[0] = deform->waveparms[0];
10239 waveparms[1] = deform->waveparms[1];
10240 waveparms[2] = deform->waveparms[2];
10241 waveparms[3] = deform->waveparms[3];
10242 // this is how a divisor of vertex influence on deformation
10243 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10244 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10245 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10247 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10248 for (j = 0;j < surface->num_vertices;j++)
10250 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
10251 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
10252 // if the wavefunc depends on time, evaluate it per-vertex
10255 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
10256 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10258 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
10261 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10262 rsurface.vertex3f_bufferobject = 0;
10263 rsurface.vertex3f_bufferoffset = 0;
10265 case Q3DEFORM_BULGE:
10266 // deform vertex array to make the surface have moving bulges
10267 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10269 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10270 for (j = 0;j < surface->num_vertices;j++)
10272 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
10273 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10276 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10277 rsurface.vertex3f_bufferobject = 0;
10278 rsurface.vertex3f_bufferoffset = 0;
10280 case Q3DEFORM_MOVE:
10281 // deform vertex array
10282 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10283 VectorScale(deform->parms, scale, waveparms);
10284 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10286 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10287 for (j = 0;j < surface->num_vertices;j++)
10288 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10290 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10291 rsurface.vertex3f_bufferobject = 0;
10292 rsurface.vertex3f_bufferoffset = 0;
10296 // generate texcoords based on the chosen texcoord source
10297 switch(rsurface.texture->tcgen.tcgen)
10300 case Q3TCGEN_TEXTURE:
10301 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10302 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
10303 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
10305 case Q3TCGEN_LIGHTMAP:
10306 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
10307 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10308 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10310 case Q3TCGEN_VECTOR:
10311 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10313 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10314 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)
10316 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10317 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10320 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10321 rsurface.texcoordtexture2f_bufferobject = 0;
10322 rsurface.texcoordtexture2f_bufferoffset = 0;
10324 case Q3TCGEN_ENVIRONMENT:
10325 // make environment reflections using a spheremap
10326 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10328 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10329 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10330 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10331 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10332 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10334 // identical to Q3A's method, but executed in worldspace so
10335 // carried models can be shiny too
10337 float viewer[3], d, reflected[3], worldreflected[3];
10339 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10340 // VectorNormalize(viewer);
10342 d = DotProduct(normal, viewer);
10344 reflected[0] = normal[0]*2*d - viewer[0];
10345 reflected[1] = normal[1]*2*d - viewer[1];
10346 reflected[2] = normal[2]*2*d - viewer[2];
10347 // note: this is proportinal to viewer, so we can normalize later
10349 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10350 VectorNormalize(worldreflected);
10352 // note: this sphere map only uses world x and z!
10353 // so positive and negative y will LOOK THE SAME.
10354 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10355 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10358 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10359 rsurface.texcoordtexture2f_bufferobject = 0;
10360 rsurface.texcoordtexture2f_bufferoffset = 0;
10363 // the only tcmod that needs software vertex processing is turbulent, so
10364 // check for it here and apply the changes if needed
10365 // and we only support that as the first one
10366 // (handling a mixture of turbulent and other tcmods would be problematic
10367 // without punting it entirely to a software path)
10368 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10370 amplitude = rsurface.texture->tcmods[0].parms[1];
10371 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10372 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10374 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10375 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)
10377 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10378 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10381 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10382 rsurface.texcoordtexture2f_bufferobject = 0;
10383 rsurface.texcoordtexture2f_bufferoffset = 0;
10385 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10386 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10387 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10388 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10391 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10394 const msurface_t *surface = texturesurfacelist[0];
10395 const msurface_t *surface2;
10400 // TODO: lock all array ranges before render, rather than on each surface
10401 if (texturenumsurfaces == 1)
10402 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);
10403 else if (r_batchmode.integer == 2)
10405 #define MAXBATCHTRIANGLES 65536
10406 int batchtriangles = 0;
10407 static int batchelements[MAXBATCHTRIANGLES*3];
10408 for (i = 0;i < texturenumsurfaces;i = j)
10410 surface = texturesurfacelist[i];
10412 if (surface->num_triangles > MAXBATCHTRIANGLES)
10414 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);
10417 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10418 batchtriangles = surface->num_triangles;
10419 firstvertex = surface->num_firstvertex;
10420 endvertex = surface->num_firstvertex + surface->num_vertices;
10421 for (;j < texturenumsurfaces;j++)
10423 surface2 = texturesurfacelist[j];
10424 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10426 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10427 batchtriangles += surface2->num_triangles;
10428 firstvertex = min(firstvertex, surface2->num_firstvertex);
10429 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10431 surface2 = texturesurfacelist[j-1];
10432 numvertices = endvertex - firstvertex;
10433 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10436 else if (r_batchmode.integer == 1)
10438 for (i = 0;i < texturenumsurfaces;i = j)
10440 surface = texturesurfacelist[i];
10441 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10442 if (texturesurfacelist[j] != surface2)
10444 surface2 = texturesurfacelist[j-1];
10445 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10446 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10447 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10452 for (i = 0;i < texturenumsurfaces;i++)
10454 surface = texturesurfacelist[i];
10455 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);
10460 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10462 switch(vid.renderpath)
10464 case RENDERPATH_CGGL:
10466 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10467 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10470 case RENDERPATH_GL20:
10471 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10472 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10474 case RENDERPATH_GL13:
10475 case RENDERPATH_GL11:
10476 R_Mesh_TexBind(0, surface->lightmaptexture);
10481 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10483 // pick the closest matching water plane and bind textures
10484 int planeindex, vertexindex;
10488 r_waterstate_waterplane_t *p, *bestp;
10491 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10493 if(p->camera_entity != rsurface.texture->camera_entity)
10496 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10498 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10499 d += fabs(PlaneDiff(vert, &p->plane));
10501 if (bestd > d || !bestp)
10507 switch(vid.renderpath)
10509 case RENDERPATH_CGGL:
10511 if (r_cg_permutation->fp_Texture_Refraction) {CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR}
10512 else if (r_cg_permutation->fp_Texture_First) {CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR}
10513 if (r_cg_permutation->fp_Texture_Reflection) {CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR}
10516 case RENDERPATH_GL20:
10517 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10518 else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
10519 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10521 case RENDERPATH_GL13:
10522 case RENDERPATH_GL11:
10527 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10530 const msurface_t *surface;
10531 if (r_waterstate.renderingscene)
10533 for (i = 0;i < texturenumsurfaces;i++)
10535 surface = texturesurfacelist[i];
10536 RSurf_BindLightmapForSurface(surface);
10537 RSurf_BindReflectionForSurface(surface);
10538 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);
10542 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10546 const msurface_t *surface = texturesurfacelist[0];
10547 const msurface_t *surface2;
10552 if (texturenumsurfaces == 1)
10554 RSurf_BindLightmapForSurface(surface);
10555 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);
10557 else if (r_batchmode.integer == 2)
10559 int batchtriangles = 0;
10560 static int batchelements[MAXBATCHTRIANGLES*3];
10561 for (i = 0;i < texturenumsurfaces;i = j)
10563 surface = texturesurfacelist[i];
10564 RSurf_BindLightmapForSurface(surface);
10566 if (surface->num_triangles > MAXBATCHTRIANGLES)
10568 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);
10571 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10572 batchtriangles = surface->num_triangles;
10573 firstvertex = surface->num_firstvertex;
10574 endvertex = surface->num_firstvertex + surface->num_vertices;
10575 for (;j < texturenumsurfaces;j++)
10577 surface2 = texturesurfacelist[j];
10578 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10580 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10581 batchtriangles += surface2->num_triangles;
10582 firstvertex = min(firstvertex, surface2->num_firstvertex);
10583 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10585 surface2 = texturesurfacelist[j-1];
10586 numvertices = endvertex - firstvertex;
10587 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10590 else if (r_batchmode.integer == 1)
10593 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10594 for (i = 0;i < texturenumsurfaces;i = j)
10596 surface = texturesurfacelist[i];
10597 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10598 if (texturesurfacelist[j] != surface2)
10600 Con_Printf(" %i", j - i);
10603 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10605 for (i = 0;i < texturenumsurfaces;i = j)
10607 surface = texturesurfacelist[i];
10608 RSurf_BindLightmapForSurface(surface);
10609 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10610 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10613 Con_Printf(" %i", j - i);
10615 surface2 = texturesurfacelist[j-1];
10616 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10617 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10618 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10626 for (i = 0;i < texturenumsurfaces;i++)
10628 surface = texturesurfacelist[i];
10629 RSurf_BindLightmapForSurface(surface);
10630 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);
10635 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10638 int texturesurfaceindex;
10639 if (r_showsurfaces.integer == 2)
10641 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10643 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10644 for (j = 0;j < surface->num_triangles;j++)
10646 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10647 GL_Color(f, f, f, 1);
10648 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10654 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10656 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10657 int k = (int)(((size_t)surface) / sizeof(msurface_t));
10658 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);
10659 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);
10664 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10666 int texturesurfaceindex;
10670 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10672 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10673 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)
10681 rsurface.lightmapcolor4f = rsurface.array_color4f;
10682 rsurface.lightmapcolor4f_bufferobject = 0;
10683 rsurface.lightmapcolor4f_bufferoffset = 0;
10686 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10688 int texturesurfaceindex;
10694 if (rsurface.lightmapcolor4f)
10696 // generate color arrays for the surfaces in this list
10697 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10699 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10700 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)
10702 f = RSurf_FogVertex(v);
10712 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10714 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10715 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)
10717 f = RSurf_FogVertex(v);
10725 rsurface.lightmapcolor4f = rsurface.array_color4f;
10726 rsurface.lightmapcolor4f_bufferobject = 0;
10727 rsurface.lightmapcolor4f_bufferoffset = 0;
10730 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10732 int texturesurfaceindex;
10738 if (!rsurface.lightmapcolor4f)
10740 // generate color arrays for the surfaces in this list
10741 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10743 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10744 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)
10746 f = RSurf_FogVertex(v);
10747 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10748 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10749 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10753 rsurface.lightmapcolor4f = rsurface.array_color4f;
10754 rsurface.lightmapcolor4f_bufferobject = 0;
10755 rsurface.lightmapcolor4f_bufferoffset = 0;
10758 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10760 int texturesurfaceindex;
10764 if (!rsurface.lightmapcolor4f)
10766 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10768 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10769 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)
10777 rsurface.lightmapcolor4f = rsurface.array_color4f;
10778 rsurface.lightmapcolor4f_bufferobject = 0;
10779 rsurface.lightmapcolor4f_bufferoffset = 0;
10782 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10784 int texturesurfaceindex;
10788 if (!rsurface.lightmapcolor4f)
10790 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10792 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10793 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)
10795 c2[0] = c[0] + r_refdef.scene.ambient;
10796 c2[1] = c[1] + r_refdef.scene.ambient;
10797 c2[2] = c[2] + r_refdef.scene.ambient;
10801 rsurface.lightmapcolor4f = rsurface.array_color4f;
10802 rsurface.lightmapcolor4f_bufferobject = 0;
10803 rsurface.lightmapcolor4f_bufferoffset = 0;
10806 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10809 rsurface.lightmapcolor4f = NULL;
10810 rsurface.lightmapcolor4f_bufferobject = 0;
10811 rsurface.lightmapcolor4f_bufferoffset = 0;
10812 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10813 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10814 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10815 GL_Color(r, g, b, a);
10816 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10819 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10821 // TODO: optimize applyfog && applycolor case
10822 // just apply fog if necessary, and tint the fog color array if necessary
10823 rsurface.lightmapcolor4f = NULL;
10824 rsurface.lightmapcolor4f_bufferobject = 0;
10825 rsurface.lightmapcolor4f_bufferoffset = 0;
10826 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10827 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10828 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10829 GL_Color(r, g, b, a);
10830 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10833 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10835 int texturesurfaceindex;
10839 if (texturesurfacelist[0]->lightmapinfo)
10841 // generate color arrays for the surfaces in this list
10842 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10844 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10845 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10847 if (surface->lightmapinfo->samples)
10849 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10850 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10851 VectorScale(lm, scale, c);
10852 if (surface->lightmapinfo->styles[1] != 255)
10854 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10856 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10857 VectorMA(c, scale, lm, c);
10858 if (surface->lightmapinfo->styles[2] != 255)
10861 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10862 VectorMA(c, scale, lm, c);
10863 if (surface->lightmapinfo->styles[3] != 255)
10866 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10867 VectorMA(c, scale, lm, c);
10877 rsurface.lightmapcolor4f = rsurface.array_color4f;
10878 rsurface.lightmapcolor4f_bufferobject = 0;
10879 rsurface.lightmapcolor4f_bufferoffset = 0;
10883 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10884 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10885 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10887 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10888 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10889 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10890 GL_Color(r, g, b, a);
10891 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10894 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10896 int texturesurfaceindex;
10903 vec3_t ambientcolor;
10904 vec3_t diffusecolor;
10908 VectorCopy(rsurface.modellight_lightdir, lightdir);
10909 f = 0.5f * r_refdef.lightmapintensity;
10910 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10911 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10912 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10913 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10914 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10915 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10917 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10919 // generate color arrays for the surfaces in this list
10920 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10922 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10923 int numverts = surface->num_vertices;
10924 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10925 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10926 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10927 // q3-style directional shading
10928 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10930 if ((f = DotProduct(n, lightdir)) > 0)
10931 VectorMA(ambientcolor, f, diffusecolor, c);
10933 VectorCopy(ambientcolor, c);
10941 rsurface.lightmapcolor4f = rsurface.array_color4f;
10942 rsurface.lightmapcolor4f_bufferobject = 0;
10943 rsurface.lightmapcolor4f_bufferoffset = 0;
10944 *applycolor = false;
10948 *r = ambientcolor[0];
10949 *g = ambientcolor[1];
10950 *b = ambientcolor[2];
10951 rsurface.lightmapcolor4f = NULL;
10952 rsurface.lightmapcolor4f_bufferobject = 0;
10953 rsurface.lightmapcolor4f_bufferoffset = 0;
10957 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10959 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10960 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10961 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10962 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10963 GL_Color(r, g, b, a);
10964 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10967 void RSurf_SetupDepthAndCulling(void)
10969 // submodels are biased to avoid z-fighting with world surfaces that they
10970 // may be exactly overlapping (avoids z-fighting artifacts on certain
10971 // doors and things in Quake maps)
10972 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10973 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10974 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10975 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10978 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10980 // transparent sky would be ridiculous
10981 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10983 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10984 skyrenderlater = true;
10985 RSurf_SetupDepthAndCulling();
10986 GL_DepthMask(true);
10987 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10988 // skymasking on them, and Quake3 never did sky masking (unlike
10989 // software Quake and software Quake2), so disable the sky masking
10990 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10991 // and skymasking also looks very bad when noclipping outside the
10992 // level, so don't use it then either.
10993 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10995 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10996 R_Mesh_ColorPointer(NULL, 0, 0);
10997 R_Mesh_ResetTextureState();
10998 if (skyrendermasked)
11000 R_SetupShader_DepthOrShadow();
11001 // depth-only (masking)
11002 GL_ColorMask(0,0,0,0);
11003 // just to make sure that braindead drivers don't draw
11004 // anything despite that colormask...
11005 GL_BlendFunc(GL_ZERO, GL_ONE);
11009 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11011 GL_BlendFunc(GL_ONE, GL_ZERO);
11013 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11014 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11015 if (skyrendermasked)
11016 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11018 R_Mesh_ResetTextureState();
11019 GL_Color(1, 1, 1, 1);
11022 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
11023 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
11024 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11026 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
11028 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
11031 // render screenspace normalmap to texture
11032 GL_DepthMask(true);
11033 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
11034 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11036 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
11038 // render water or distortion background, then blend surface on top
11039 GL_DepthMask(true);
11040 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
11041 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11042 GL_DepthMask(false);
11043 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11044 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11045 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11047 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11051 // render surface normally
11052 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11053 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11054 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
11055 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11056 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11057 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11059 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11063 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11065 // OpenGL 1.3 path - anything not completely ancient
11066 int texturesurfaceindex;
11067 qboolean applycolor;
11070 const texturelayer_t *layer;
11071 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11073 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11076 int layertexrgbscale;
11077 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11079 if (layerindex == 0)
11080 GL_AlphaTest(true);
11083 GL_AlphaTest(false);
11084 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11087 GL_DepthMask(layer->depthmask && writedepth);
11088 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11089 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11091 layertexrgbscale = 4;
11092 VectorScale(layer->color, 0.25f, layercolor);
11094 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11096 layertexrgbscale = 2;
11097 VectorScale(layer->color, 0.5f, layercolor);
11101 layertexrgbscale = 1;
11102 VectorScale(layer->color, 1.0f, layercolor);
11104 layercolor[3] = layer->color[3];
11105 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11106 R_Mesh_ColorPointer(NULL, 0, 0);
11107 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11108 switch (layer->type)
11110 case TEXTURELAYERTYPE_LITTEXTURE:
11111 // single-pass lightmapped texture with 2x rgbscale
11112 R_Mesh_TexBind(0, r_texture_white);
11113 R_Mesh_TexMatrix(0, NULL);
11114 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11115 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11116 R_Mesh_TexBind(1, layer->texture);
11117 R_Mesh_TexMatrix(1, &layer->texmatrix);
11118 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11119 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11120 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11121 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11122 else if (rsurface.uselightmaptexture)
11123 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11125 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11127 case TEXTURELAYERTYPE_TEXTURE:
11128 // singletexture unlit texture with transparency support
11129 R_Mesh_TexBind(0, layer->texture);
11130 R_Mesh_TexMatrix(0, &layer->texmatrix);
11131 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11132 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11133 R_Mesh_TexBind(1, 0);
11134 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11135 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11137 case TEXTURELAYERTYPE_FOG:
11138 // singletexture fogging
11139 if (layer->texture)
11141 R_Mesh_TexBind(0, layer->texture);
11142 R_Mesh_TexMatrix(0, &layer->texmatrix);
11143 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11144 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11148 R_Mesh_TexBind(0, 0);
11149 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11151 R_Mesh_TexBind(1, 0);
11152 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11153 // generate a color array for the fog pass
11154 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11155 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11161 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11162 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)
11164 f = 1 - RSurf_FogVertex(v);
11165 c[0] = layercolor[0];
11166 c[1] = layercolor[1];
11167 c[2] = layercolor[2];
11168 c[3] = f * layercolor[3];
11171 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11174 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11178 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11180 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11181 GL_AlphaTest(false);
11185 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11187 // OpenGL 1.1 - crusty old voodoo path
11188 int texturesurfaceindex;
11191 const texturelayer_t *layer;
11192 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11194 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11196 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11198 if (layerindex == 0)
11199 GL_AlphaTest(true);
11202 GL_AlphaTest(false);
11203 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11206 GL_DepthMask(layer->depthmask && writedepth);
11207 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11208 R_Mesh_ColorPointer(NULL, 0, 0);
11209 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11210 switch (layer->type)
11212 case TEXTURELAYERTYPE_LITTEXTURE:
11213 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
11215 // two-pass lit texture with 2x rgbscale
11216 // first the lightmap pass
11217 R_Mesh_TexBind(0, r_texture_white);
11218 R_Mesh_TexMatrix(0, NULL);
11219 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11220 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11221 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11222 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11223 else if (rsurface.uselightmaptexture)
11224 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11226 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11227 // then apply the texture to it
11228 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11229 R_Mesh_TexBind(0, layer->texture);
11230 R_Mesh_TexMatrix(0, &layer->texmatrix);
11231 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11232 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11233 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);
11237 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11238 R_Mesh_TexBind(0, layer->texture);
11239 R_Mesh_TexMatrix(0, &layer->texmatrix);
11240 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11241 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11242 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11243 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);
11245 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);
11248 case TEXTURELAYERTYPE_TEXTURE:
11249 // singletexture unlit texture with transparency support
11250 R_Mesh_TexBind(0, layer->texture);
11251 R_Mesh_TexMatrix(0, &layer->texmatrix);
11252 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11253 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11254 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);
11256 case TEXTURELAYERTYPE_FOG:
11257 // singletexture fogging
11258 if (layer->texture)
11260 R_Mesh_TexBind(0, layer->texture);
11261 R_Mesh_TexMatrix(0, &layer->texmatrix);
11262 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11263 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11267 R_Mesh_TexBind(0, 0);
11268 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11270 // generate a color array for the fog pass
11271 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11272 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11278 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11279 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)
11281 f = 1 - RSurf_FogVertex(v);
11282 c[0] = layer->color[0];
11283 c[1] = layer->color[1];
11284 c[2] = layer->color[2];
11285 c[3] = f * layer->color[3];
11288 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11291 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11295 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11297 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11298 GL_AlphaTest(false);
11302 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11306 GL_AlphaTest(false);
11307 R_Mesh_ColorPointer(NULL, 0, 0);
11308 R_Mesh_ResetTextureState();
11309 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11311 if(rsurface.texture && rsurface.texture->currentskinframe)
11313 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11314 c[3] *= rsurface.texture->currentalpha;
11324 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11326 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11327 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11328 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11331 // brighten it up (as texture value 127 means "unlit")
11332 c[0] *= 2 * r_refdef.view.colorscale;
11333 c[1] *= 2 * r_refdef.view.colorscale;
11334 c[2] *= 2 * r_refdef.view.colorscale;
11336 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11337 c[3] *= r_wateralpha.value;
11339 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11341 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11342 GL_DepthMask(false);
11344 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11346 GL_BlendFunc(GL_ONE, GL_ONE);
11347 GL_DepthMask(false);
11349 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11351 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11352 GL_DepthMask(false);
11354 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11356 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11357 GL_DepthMask(false);
11361 GL_BlendFunc(GL_ONE, GL_ZERO);
11362 GL_DepthMask(writedepth);
11365 rsurface.lightmapcolor4f = NULL;
11367 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11369 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11371 rsurface.lightmapcolor4f = NULL;
11372 rsurface.lightmapcolor4f_bufferobject = 0;
11373 rsurface.lightmapcolor4f_bufferoffset = 0;
11375 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11377 qboolean applycolor = true;
11380 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11382 r_refdef.lightmapintensity = 1;
11383 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11384 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11388 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11390 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11391 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11392 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11395 if(!rsurface.lightmapcolor4f)
11396 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11398 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11399 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11400 if(r_refdef.fogenabled)
11401 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11403 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11404 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11407 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11410 RSurf_SetupDepthAndCulling();
11411 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11413 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11416 switch (vid.renderpath)
11418 case RENDERPATH_GL20:
11419 case RENDERPATH_CGGL:
11420 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11422 case RENDERPATH_GL13:
11423 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11425 case RENDERPATH_GL11:
11426 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11432 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11435 RSurf_SetupDepthAndCulling();
11436 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11438 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11441 switch (vid.renderpath)
11443 case RENDERPATH_GL20:
11444 case RENDERPATH_CGGL:
11445 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11447 case RENDERPATH_GL13:
11448 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11450 case RENDERPATH_GL11:
11451 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11457 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11460 int texturenumsurfaces, endsurface;
11461 texture_t *texture;
11462 const msurface_t *surface;
11463 #define MAXBATCH_TRANSPARENTSURFACES 256
11464 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
11466 // if the model is static it doesn't matter what value we give for
11467 // wantnormals and wanttangents, so this logic uses only rules applicable
11468 // to a model, knowing that they are meaningless otherwise
11469 if (ent == r_refdef.scene.worldentity)
11470 RSurf_ActiveWorldEntity();
11471 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11472 RSurf_ActiveModelEntity(ent, false, false, false);
11475 switch (vid.renderpath)
11477 case RENDERPATH_GL20:
11478 case RENDERPATH_CGGL:
11479 RSurf_ActiveModelEntity(ent, true, true, false);
11481 case RENDERPATH_GL13:
11482 case RENDERPATH_GL11:
11483 RSurf_ActiveModelEntity(ent, true, false, false);
11488 if (r_transparentdepthmasking.integer)
11490 qboolean setup = false;
11491 for (i = 0;i < numsurfaces;i = j)
11494 surface = rsurface.modelsurfaces + surfacelist[i];
11495 texture = surface->texture;
11496 rsurface.texture = R_GetCurrentTexture(texture);
11497 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11498 // scan ahead until we find a different texture
11499 endsurface = min(i + 1024, numsurfaces);
11500 texturenumsurfaces = 0;
11501 texturesurfacelist[texturenumsurfaces++] = surface;
11502 for (;j < endsurface;j++)
11504 surface = rsurface.modelsurfaces + surfacelist[j];
11505 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11507 texturesurfacelist[texturenumsurfaces++] = surface;
11509 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11511 // render the range of surfaces as depth
11515 GL_ColorMask(0,0,0,0);
11517 GL_DepthTest(true);
11518 GL_BlendFunc(GL_ONE, GL_ZERO);
11519 GL_DepthMask(true);
11520 GL_AlphaTest(false);
11521 R_Mesh_ColorPointer(NULL, 0, 0);
11522 R_Mesh_ResetTextureState();
11523 R_SetupShader_DepthOrShadow();
11525 RSurf_SetupDepthAndCulling();
11526 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11527 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11530 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11533 for (i = 0;i < numsurfaces;i = j)
11536 surface = rsurface.modelsurfaces + surfacelist[i];
11537 texture = surface->texture;
11538 rsurface.texture = R_GetCurrentTexture(texture);
11539 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11540 // scan ahead until we find a different texture
11541 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
11542 texturenumsurfaces = 0;
11543 texturesurfacelist[texturenumsurfaces++] = surface;
11544 for (;j < endsurface;j++)
11546 surface = rsurface.modelsurfaces + surfacelist[j];
11547 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11549 texturesurfacelist[texturenumsurfaces++] = surface;
11551 // render the range of surfaces
11552 if (ent == r_refdef.scene.worldentity)
11553 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11555 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11557 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11558 GL_AlphaTest(false);
11561 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11563 // transparent surfaces get pushed off into the transparent queue
11564 int surfacelistindex;
11565 const msurface_t *surface;
11566 vec3_t tempcenter, center;
11567 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11569 surface = texturesurfacelist[surfacelistindex];
11570 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11571 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11572 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11573 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11574 if (queueentity->transparent_offset) // transparent offset
11576 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11577 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11578 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11580 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11584 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11586 const entity_render_t *queueentity = r_refdef.scene.worldentity;
11590 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11592 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11594 RSurf_SetupDepthAndCulling();
11595 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11596 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11600 if (!rsurface.texture->currentnumlayers)
11602 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11603 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11605 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11607 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11609 RSurf_SetupDepthAndCulling();
11610 GL_AlphaTest(false);
11611 R_Mesh_ColorPointer(NULL, 0, 0);
11612 R_Mesh_ResetTextureState();
11613 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11614 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11615 GL_DepthMask(true);
11616 GL_BlendFunc(GL_ONE, GL_ZERO);
11617 GL_Color(0, 0, 0, 1);
11618 GL_DepthTest(writedepth);
11619 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11621 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11623 RSurf_SetupDepthAndCulling();
11624 GL_AlphaTest(false);
11625 R_Mesh_ColorPointer(NULL, 0, 0);
11626 R_Mesh_ResetTextureState();
11627 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11628 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11629 GL_DepthMask(true);
11630 GL_BlendFunc(GL_ONE, GL_ZERO);
11631 GL_DepthTest(true);
11632 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11634 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11635 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11636 else if (!rsurface.texture->currentnumlayers)
11638 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11640 // in the deferred case, transparent surfaces were queued during prepass
11641 if (!r_shadow_usingdeferredprepass)
11642 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11646 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11647 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11652 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11655 texture_t *texture;
11656 // break the surface list down into batches by texture and use of lightmapping
11657 for (i = 0;i < numsurfaces;i = j)
11660 // texture is the base texture pointer, rsurface.texture is the
11661 // current frame/skin the texture is directing us to use (for example
11662 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11663 // use skin 1 instead)
11664 texture = surfacelist[i]->texture;
11665 rsurface.texture = R_GetCurrentTexture(texture);
11666 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11667 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11669 // if this texture is not the kind we want, skip ahead to the next one
11670 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11674 // simply scan ahead until we find a different texture or lightmap state
11675 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11677 // render the range of surfaces
11678 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11682 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11687 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11689 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11691 RSurf_SetupDepthAndCulling();
11692 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11693 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11697 if (!rsurface.texture->currentnumlayers)
11699 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11700 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11702 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11704 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11706 RSurf_SetupDepthAndCulling();
11707 GL_AlphaTest(false);
11708 R_Mesh_ColorPointer(NULL, 0, 0);
11709 R_Mesh_ResetTextureState();
11710 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11711 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11712 GL_DepthMask(true);
11713 GL_BlendFunc(GL_ONE, GL_ZERO);
11714 GL_Color(0, 0, 0, 1);
11715 GL_DepthTest(writedepth);
11716 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11718 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11720 RSurf_SetupDepthAndCulling();
11721 GL_AlphaTest(false);
11722 R_Mesh_ColorPointer(NULL, 0, 0);
11723 R_Mesh_ResetTextureState();
11724 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11725 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11726 GL_DepthMask(true);
11727 GL_BlendFunc(GL_ONE, GL_ZERO);
11728 GL_DepthTest(true);
11729 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11731 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11732 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11733 else if (!rsurface.texture->currentnumlayers)
11735 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11737 // in the deferred case, transparent surfaces were queued during prepass
11738 if (!r_shadow_usingdeferredprepass)
11739 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11743 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11744 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11749 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11752 texture_t *texture;
11753 // break the surface list down into batches by texture and use of lightmapping
11754 for (i = 0;i < numsurfaces;i = j)
11757 // texture is the base texture pointer, rsurface.texture is the
11758 // current frame/skin the texture is directing us to use (for example
11759 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11760 // use skin 1 instead)
11761 texture = surfacelist[i]->texture;
11762 rsurface.texture = R_GetCurrentTexture(texture);
11763 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11764 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11766 // if this texture is not the kind we want, skip ahead to the next one
11767 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11771 // simply scan ahead until we find a different texture or lightmap state
11772 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11774 // render the range of surfaces
11775 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11779 float locboxvertex3f[6*4*3] =
11781 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11782 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11783 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11784 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11785 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11786 1,0,0, 0,0,0, 0,1,0, 1,1,0
11789 unsigned short locboxelements[6*2*3] =
11794 12,13,14, 12,14,15,
11795 16,17,18, 16,18,19,
11799 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11802 cl_locnode_t *loc = (cl_locnode_t *)ent;
11804 float vertex3f[6*4*3];
11806 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11807 GL_DepthMask(false);
11808 GL_DepthRange(0, 1);
11809 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11810 GL_DepthTest(true);
11811 GL_CullFace(GL_NONE);
11812 R_EntityMatrix(&identitymatrix);
11814 R_Mesh_VertexPointer(vertex3f, 0, 0);
11815 R_Mesh_ColorPointer(NULL, 0, 0);
11816 R_Mesh_ResetTextureState();
11817 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11819 i = surfacelist[0];
11820 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11821 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11822 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11823 surfacelist[0] < 0 ? 0.5f : 0.125f);
11825 if (VectorCompare(loc->mins, loc->maxs))
11827 VectorSet(size, 2, 2, 2);
11828 VectorMA(loc->mins, -0.5f, size, mins);
11832 VectorCopy(loc->mins, mins);
11833 VectorSubtract(loc->maxs, loc->mins, size);
11836 for (i = 0;i < 6*4*3;)
11837 for (j = 0;j < 3;j++, i++)
11838 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11840 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11843 void R_DrawLocs(void)
11846 cl_locnode_t *loc, *nearestloc;
11848 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11849 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11851 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11852 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11856 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11858 if (decalsystem->decals)
11859 Mem_Free(decalsystem->decals);
11860 memset(decalsystem, 0, sizeof(*decalsystem));
11863 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)
11866 tridecal_t *decals;
11869 // expand or initialize the system
11870 if (decalsystem->maxdecals <= decalsystem->numdecals)
11872 decalsystem_t old = *decalsystem;
11873 qboolean useshortelements;
11874 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11875 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11876 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)));
11877 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11878 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11879 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11880 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11881 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11882 if (decalsystem->numdecals)
11883 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11885 Mem_Free(old.decals);
11886 for (i = 0;i < decalsystem->maxdecals*3;i++)
11887 decalsystem->element3i[i] = i;
11888 if (useshortelements)
11889 for (i = 0;i < decalsystem->maxdecals*3;i++)
11890 decalsystem->element3s[i] = i;
11893 // grab a decal and search for another free slot for the next one
11894 decals = decalsystem->decals;
11895 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11896 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11898 decalsystem->freedecal = i;
11899 if (decalsystem->numdecals <= i)
11900 decalsystem->numdecals = i + 1;
11902 // initialize the decal
11904 decal->triangleindex = triangleindex;
11905 decal->surfaceindex = surfaceindex;
11906 decal->decalsequence = decalsequence;
11907 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11908 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11909 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11910 decal->color4ub[0][3] = 255;
11911 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11912 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11913 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11914 decal->color4ub[1][3] = 255;
11915 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11916 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11917 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11918 decal->color4ub[2][3] = 255;
11919 decal->vertex3f[0][0] = v0[0];
11920 decal->vertex3f[0][1] = v0[1];
11921 decal->vertex3f[0][2] = v0[2];
11922 decal->vertex3f[1][0] = v1[0];
11923 decal->vertex3f[1][1] = v1[1];
11924 decal->vertex3f[1][2] = v1[2];
11925 decal->vertex3f[2][0] = v2[0];
11926 decal->vertex3f[2][1] = v2[1];
11927 decal->vertex3f[2][2] = v2[2];
11928 decal->texcoord2f[0][0] = t0[0];
11929 decal->texcoord2f[0][1] = t0[1];
11930 decal->texcoord2f[1][0] = t1[0];
11931 decal->texcoord2f[1][1] = t1[1];
11932 decal->texcoord2f[2][0] = t2[0];
11933 decal->texcoord2f[2][1] = t2[1];
11936 extern cvar_t cl_decals_bias;
11937 extern cvar_t cl_decals_models;
11938 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11939 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)
11941 matrix4x4_t projection;
11942 decalsystem_t *decalsystem;
11945 const float *vertex3f;
11946 const msurface_t *surface;
11947 const msurface_t *surfaces;
11948 const int *surfacelist;
11949 const texture_t *texture;
11951 int numsurfacelist;
11952 int surfacelistindex;
11959 float localorigin[3];
11960 float localnormal[3];
11961 float localmins[3];
11962 float localmaxs[3];
11968 float planes[6][4];
11970 float points[2][9][3];
11974 decalsystem = &ent->decalsystem;
11975 model = ent->model;
11976 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11978 R_DecalSystem_Reset(&ent->decalsystem);
11982 if (!model->brush.data_nodes && !cl_decals_models.integer)
11984 if (decalsystem->model)
11985 R_DecalSystem_Reset(decalsystem);
11989 if (decalsystem->model != model)
11990 R_DecalSystem_Reset(decalsystem);
11991 decalsystem->model = model;
11993 RSurf_ActiveModelEntity(ent, false, false, false);
11995 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11996 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11997 VectorNormalize(localnormal);
11998 localsize = worldsize*rsurface.inversematrixscale;
11999 localmins[0] = localorigin[0] - localsize;
12000 localmins[1] = localorigin[1] - localsize;
12001 localmins[2] = localorigin[2] - localsize;
12002 localmaxs[0] = localorigin[0] + localsize;
12003 localmaxs[1] = localorigin[1] + localsize;
12004 localmaxs[2] = localorigin[2] + localsize;
12006 //VectorCopy(localnormal, planes[4]);
12007 //VectorVectors(planes[4], planes[2], planes[0]);
12008 AnglesFromVectors(angles, localnormal, NULL, false);
12009 AngleVectors(angles, planes[0], planes[2], planes[4]);
12010 VectorNegate(planes[0], planes[1]);
12011 VectorNegate(planes[2], planes[3]);
12012 VectorNegate(planes[4], planes[5]);
12013 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12014 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12015 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12016 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12017 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12018 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12023 matrix4x4_t forwardprojection;
12024 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12025 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12030 float projectionvector[4][3];
12031 VectorScale(planes[0], ilocalsize, projectionvector[0]);
12032 VectorScale(planes[2], ilocalsize, projectionvector[1]);
12033 VectorScale(planes[4], ilocalsize, projectionvector[2]);
12034 projectionvector[0][0] = planes[0][0] * ilocalsize;
12035 projectionvector[0][1] = planes[1][0] * ilocalsize;
12036 projectionvector[0][2] = planes[2][0] * ilocalsize;
12037 projectionvector[1][0] = planes[0][1] * ilocalsize;
12038 projectionvector[1][1] = planes[1][1] * ilocalsize;
12039 projectionvector[1][2] = planes[2][1] * ilocalsize;
12040 projectionvector[2][0] = planes[0][2] * ilocalsize;
12041 projectionvector[2][1] = planes[1][2] * ilocalsize;
12042 projectionvector[2][2] = planes[2][2] * ilocalsize;
12043 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12044 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12045 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12046 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12050 dynamic = model->surfmesh.isanimated;
12051 vertex3f = rsurface.modelvertex3f;
12052 numsurfacelist = model->nummodelsurfaces;
12053 surfacelist = model->sortedmodelsurfaces;
12054 surfaces = model->data_surfaces;
12055 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12057 surfaceindex = surfacelist[surfacelistindex];
12058 surface = surfaces + surfaceindex;
12059 // check cull box first because it rejects more than any other check
12060 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12062 // skip transparent surfaces
12063 texture = surface->texture;
12064 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12066 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12068 numtriangles = surface->num_triangles;
12069 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
12071 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12073 index = 3*e[cornerindex];
12074 VectorCopy(vertex3f + index, v[cornerindex]);
12077 //TriangleNormal(v[0], v[1], v[2], normal);
12078 //if (DotProduct(normal, localnormal) < 0.0f)
12080 // clip by each of the box planes formed from the projection matrix
12081 // if anything survives, we emit the decal
12082 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]);
12085 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]);
12088 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]);
12091 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]);
12094 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]);
12097 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]);
12100 // some part of the triangle survived, so we have to accept it...
12103 // dynamic always uses the original triangle
12105 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12107 index = 3*e[cornerindex];
12108 VectorCopy(vertex3f + index, v[cornerindex]);
12111 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12113 // convert vertex positions to texcoords
12114 Matrix4x4_Transform(&projection, v[cornerindex], temp);
12115 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12116 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12117 // calculate distance fade from the projection origin
12118 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12119 f = bound(0.0f, f, 1.0f);
12120 c[cornerindex][0] = r * f;
12121 c[cornerindex][1] = g * f;
12122 c[cornerindex][2] = b * f;
12123 c[cornerindex][3] = 1.0f;
12124 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12127 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);
12129 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12130 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);
12135 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12136 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)
12138 int renderentityindex;
12139 float worldmins[3];
12140 float worldmaxs[3];
12141 entity_render_t *ent;
12143 if (!cl_decals_newsystem.integer)
12146 worldmins[0] = worldorigin[0] - worldsize;
12147 worldmins[1] = worldorigin[1] - worldsize;
12148 worldmins[2] = worldorigin[2] - worldsize;
12149 worldmaxs[0] = worldorigin[0] + worldsize;
12150 worldmaxs[1] = worldorigin[1] + worldsize;
12151 worldmaxs[2] = worldorigin[2] + worldsize;
12153 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12155 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12157 ent = r_refdef.scene.entities[renderentityindex];
12158 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12161 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12165 typedef struct r_decalsystem_splatqueue_s
12167 vec3_t worldorigin;
12168 vec3_t worldnormal;
12174 r_decalsystem_splatqueue_t;
12176 int r_decalsystem_numqueued = 0;
12177 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12179 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)
12181 r_decalsystem_splatqueue_t *queue;
12183 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12186 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12187 VectorCopy(worldorigin, queue->worldorigin);
12188 VectorCopy(worldnormal, queue->worldnormal);
12189 Vector4Set(queue->color, r, g, b, a);
12190 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12191 queue->worldsize = worldsize;
12192 queue->decalsequence = cl.decalsequence++;
12195 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12198 r_decalsystem_splatqueue_t *queue;
12200 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12201 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);
12202 r_decalsystem_numqueued = 0;
12205 extern cvar_t cl_decals_max;
12206 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12209 decalsystem_t *decalsystem = &ent->decalsystem;
12216 if (!decalsystem->numdecals)
12219 if (r_showsurfaces.integer)
12222 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12224 R_DecalSystem_Reset(decalsystem);
12228 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12229 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12231 if (decalsystem->lastupdatetime)
12232 frametime = (cl.time - decalsystem->lastupdatetime);
12235 decalsystem->lastupdatetime = cl.time;
12236 decal = decalsystem->decals;
12237 numdecals = decalsystem->numdecals;
12239 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12241 if (decal->color4ub[0][3])
12243 decal->lived += frametime;
12244 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12246 memset(decal, 0, sizeof(*decal));
12247 if (decalsystem->freedecal > i)
12248 decalsystem->freedecal = i;
12252 decal = decalsystem->decals;
12253 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
12256 // collapse the array by shuffling the tail decals into the gaps
12259 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12260 decalsystem->freedecal++;
12261 if (decalsystem->freedecal == numdecals)
12263 decal[decalsystem->freedecal] = decal[--numdecals];
12266 decalsystem->numdecals = numdecals;
12268 if (numdecals <= 0)
12270 // if there are no decals left, reset decalsystem
12271 R_DecalSystem_Reset(decalsystem);
12275 extern skinframe_t *decalskinframe;
12276 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12279 decalsystem_t *decalsystem = &ent->decalsystem;
12288 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12291 numdecals = decalsystem->numdecals;
12295 if (r_showsurfaces.integer)
12298 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12300 R_DecalSystem_Reset(decalsystem);
12304 // if the model is static it doesn't matter what value we give for
12305 // wantnormals and wanttangents, so this logic uses only rules applicable
12306 // to a model, knowing that they are meaningless otherwise
12307 if (ent == r_refdef.scene.worldentity)
12308 RSurf_ActiveWorldEntity();
12310 RSurf_ActiveModelEntity(ent, false, false, false);
12312 decalsystem->lastupdatetime = cl.time;
12313 decal = decalsystem->decals;
12315 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12317 // update vertex positions for animated models
12318 v3f = decalsystem->vertex3f;
12319 c4f = decalsystem->color4f;
12320 t2f = decalsystem->texcoord2f;
12321 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12323 if (!decal->color4ub[0][3])
12326 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12329 // update color values for fading decals
12330 if (decal->lived >= cl_decals_time.value)
12332 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12333 alpha *= (1.0f/255.0f);
12336 alpha = 1.0f/255.0f;
12338 c4f[ 0] = decal->color4ub[0][0] * alpha;
12339 c4f[ 1] = decal->color4ub[0][1] * alpha;
12340 c4f[ 2] = decal->color4ub[0][2] * alpha;
12342 c4f[ 4] = decal->color4ub[1][0] * alpha;
12343 c4f[ 5] = decal->color4ub[1][1] * alpha;
12344 c4f[ 6] = decal->color4ub[1][2] * alpha;
12346 c4f[ 8] = decal->color4ub[2][0] * alpha;
12347 c4f[ 9] = decal->color4ub[2][1] * alpha;
12348 c4f[10] = decal->color4ub[2][2] * alpha;
12351 t2f[0] = decal->texcoord2f[0][0];
12352 t2f[1] = decal->texcoord2f[0][1];
12353 t2f[2] = decal->texcoord2f[1][0];
12354 t2f[3] = decal->texcoord2f[1][1];
12355 t2f[4] = decal->texcoord2f[2][0];
12356 t2f[5] = decal->texcoord2f[2][1];
12358 // update vertex positions for animated models
12359 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12361 e = rsurface.modelelement3i + 3*decal->triangleindex;
12362 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12363 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12364 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12368 VectorCopy(decal->vertex3f[0], v3f);
12369 VectorCopy(decal->vertex3f[1], v3f + 3);
12370 VectorCopy(decal->vertex3f[2], v3f + 6);
12373 if (r_refdef.fogenabled)
12375 alpha = RSurf_FogVertex(v3f);
12376 VectorScale(c4f, alpha, c4f);
12377 alpha = RSurf_FogVertex(v3f + 3);
12378 VectorScale(c4f + 4, alpha, c4f + 4);
12379 alpha = RSurf_FogVertex(v3f + 6);
12380 VectorScale(c4f + 8, alpha, c4f + 8);
12391 r_refdef.stats.drawndecals += numtris;
12393 // now render the decals all at once
12394 // (this assumes they all use one particle font texture!)
12395 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);
12396 R_Mesh_ResetTextureState();
12397 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12398 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12399 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12400 GL_DepthMask(false);
12401 GL_DepthRange(0, 1);
12402 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12403 GL_DepthTest(true);
12404 GL_CullFace(GL_NONE);
12405 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12406 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12407 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12411 static void R_DrawModelDecals(void)
12415 // fade faster when there are too many decals
12416 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12417 for (i = 0;i < r_refdef.scene.numentities;i++)
12418 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12420 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12421 for (i = 0;i < r_refdef.scene.numentities;i++)
12422 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12423 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12425 R_DecalSystem_ApplySplatEntitiesQueue();
12427 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12428 for (i = 0;i < r_refdef.scene.numentities;i++)
12429 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12431 r_refdef.stats.totaldecals += numdecals;
12433 if (r_showsurfaces.integer)
12436 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12438 for (i = 0;i < r_refdef.scene.numentities;i++)
12440 if (!r_refdef.viewcache.entityvisible[i])
12442 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12443 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12447 extern cvar_t mod_collision_bih;
12448 void R_DrawDebugModel(void)
12450 entity_render_t *ent = rsurface.entity;
12451 int i, j, k, l, flagsmask;
12452 const msurface_t *surface;
12453 dp_model_t *model = ent->model;
12456 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12458 R_Mesh_ColorPointer(NULL, 0, 0);
12459 R_Mesh_ResetTextureState();
12460 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12461 GL_DepthRange(0, 1);
12462 GL_DepthTest(!r_showdisabledepthtest.integer);
12463 GL_DepthMask(false);
12464 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12466 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12470 qboolean cullbox = ent == r_refdef.scene.worldentity;
12471 const q3mbrush_t *brush;
12472 const bih_t *bih = &model->collision_bih;
12473 const bih_leaf_t *bihleaf;
12474 float vertex3f[3][3];
12475 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12477 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12479 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12481 switch (bihleaf->type)
12484 brush = model->brush.data_brushes + bihleaf->itemindex;
12485 if (brush->colbrushf && brush->colbrushf->numtriangles)
12487 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12488 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12489 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12492 case BIH_COLLISIONTRIANGLE:
12493 triangleindex = bihleaf->itemindex;
12494 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12495 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12496 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12497 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12498 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12499 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12501 case BIH_RENDERTRIANGLE:
12502 triangleindex = bihleaf->itemindex;
12503 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12504 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12505 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12506 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12507 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12508 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12514 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12516 if (r_showtris.integer || r_shownormals.integer)
12518 if (r_showdisabledepthtest.integer)
12520 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12521 GL_DepthMask(false);
12525 GL_BlendFunc(GL_ONE, GL_ZERO);
12526 GL_DepthMask(true);
12528 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12530 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12532 rsurface.texture = R_GetCurrentTexture(surface->texture);
12533 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12535 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12536 if (r_showtris.value > 0)
12538 if (!rsurface.texture->currentlayers->depthmask)
12539 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12540 else if (ent == r_refdef.scene.worldentity)
12541 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12543 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12544 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12545 R_Mesh_ColorPointer(NULL, 0, 0);
12546 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12547 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12548 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12549 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);
12550 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12553 if (r_shownormals.value < 0)
12555 qglBegin(GL_LINES);
12556 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12558 VectorCopy(rsurface.vertex3f + l * 3, v);
12559 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12560 qglVertex3f(v[0], v[1], v[2]);
12561 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12562 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12563 qglVertex3f(v[0], v[1], v[2]);
12568 if (r_shownormals.value > 0)
12570 qglBegin(GL_LINES);
12571 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12573 VectorCopy(rsurface.vertex3f + l * 3, v);
12574 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12575 qglVertex3f(v[0], v[1], v[2]);
12576 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12577 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12578 qglVertex3f(v[0], v[1], v[2]);
12582 qglBegin(GL_LINES);
12583 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12585 VectorCopy(rsurface.vertex3f + l * 3, v);
12586 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12587 qglVertex3f(v[0], v[1], v[2]);
12588 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12589 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12590 qglVertex3f(v[0], v[1], v[2]);
12594 qglBegin(GL_LINES);
12595 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12597 VectorCopy(rsurface.vertex3f + l * 3, v);
12598 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12599 qglVertex3f(v[0], v[1], v[2]);
12600 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12601 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12602 qglVertex3f(v[0], v[1], v[2]);
12609 rsurface.texture = NULL;
12613 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12614 int r_maxsurfacelist = 0;
12615 const msurface_t **r_surfacelist = NULL;
12616 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12618 int i, j, endj, flagsmask;
12619 dp_model_t *model = r_refdef.scene.worldmodel;
12620 msurface_t *surfaces;
12621 unsigned char *update;
12622 int numsurfacelist = 0;
12626 if (r_maxsurfacelist < model->num_surfaces)
12628 r_maxsurfacelist = model->num_surfaces;
12630 Mem_Free((msurface_t**)r_surfacelist);
12631 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12634 RSurf_ActiveWorldEntity();
12636 surfaces = model->data_surfaces;
12637 update = model->brushq1.lightmapupdateflags;
12639 // update light styles on this submodel
12640 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12642 model_brush_lightstyleinfo_t *style;
12643 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12645 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12647 int *list = style->surfacelist;
12648 style->value = r_refdef.scene.lightstylevalue[style->style];
12649 for (j = 0;j < style->numsurfaces;j++)
12650 update[list[j]] = true;
12655 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12659 R_DrawDebugModel();
12660 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12664 rsurface.uselightmaptexture = false;
12665 rsurface.texture = NULL;
12666 rsurface.rtlight = NULL;
12667 numsurfacelist = 0;
12668 // add visible surfaces to draw list
12669 for (i = 0;i < model->nummodelsurfaces;i++)
12671 j = model->sortedmodelsurfaces[i];
12672 if (r_refdef.viewcache.world_surfacevisible[j])
12673 r_surfacelist[numsurfacelist++] = surfaces + j;
12675 // update lightmaps if needed
12676 if (model->brushq1.firstrender)
12678 model->brushq1.firstrender = false;
12679 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12681 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12685 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12686 if (r_refdef.viewcache.world_surfacevisible[j])
12688 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12690 // don't do anything if there were no surfaces
12691 if (!numsurfacelist)
12693 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12696 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12697 GL_AlphaTest(false);
12699 // add to stats if desired
12700 if (r_speeds.integer && !skysurfaces && !depthonly)
12702 r_refdef.stats.world_surfaces += numsurfacelist;
12703 for (j = 0;j < numsurfacelist;j++)
12704 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12707 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12710 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12712 int i, j, endj, flagsmask;
12713 dp_model_t *model = ent->model;
12714 msurface_t *surfaces;
12715 unsigned char *update;
12716 int numsurfacelist = 0;
12720 if (r_maxsurfacelist < model->num_surfaces)
12722 r_maxsurfacelist = model->num_surfaces;
12724 Mem_Free((msurface_t **)r_surfacelist);
12725 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12728 // if the model is static it doesn't matter what value we give for
12729 // wantnormals and wanttangents, so this logic uses only rules applicable
12730 // to a model, knowing that they are meaningless otherwise
12731 if (ent == r_refdef.scene.worldentity)
12732 RSurf_ActiveWorldEntity();
12733 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12734 RSurf_ActiveModelEntity(ent, false, false, false);
12736 RSurf_ActiveModelEntity(ent, true, true, true);
12737 else if (depthonly)
12739 switch (vid.renderpath)
12741 case RENDERPATH_GL20:
12742 case RENDERPATH_CGGL:
12743 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12745 case RENDERPATH_GL13:
12746 case RENDERPATH_GL11:
12747 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12753 switch (vid.renderpath)
12755 case RENDERPATH_GL20:
12756 case RENDERPATH_CGGL:
12757 RSurf_ActiveModelEntity(ent, true, true, false);
12759 case RENDERPATH_GL13:
12760 case RENDERPATH_GL11:
12761 RSurf_ActiveModelEntity(ent, true, false, false);
12766 surfaces = model->data_surfaces;
12767 update = model->brushq1.lightmapupdateflags;
12769 // update light styles
12770 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12772 model_brush_lightstyleinfo_t *style;
12773 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12775 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12777 int *list = style->surfacelist;
12778 style->value = r_refdef.scene.lightstylevalue[style->style];
12779 for (j = 0;j < style->numsurfaces;j++)
12780 update[list[j]] = true;
12785 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12789 R_DrawDebugModel();
12790 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12794 rsurface.uselightmaptexture = false;
12795 rsurface.texture = NULL;
12796 rsurface.rtlight = NULL;
12797 numsurfacelist = 0;
12798 // add visible surfaces to draw list
12799 for (i = 0;i < model->nummodelsurfaces;i++)
12800 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12801 // don't do anything if there were no surfaces
12802 if (!numsurfacelist)
12804 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12807 // update lightmaps if needed
12811 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12816 R_BuildLightMap(ent, surfaces + j);
12821 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12823 R_BuildLightMap(ent, surfaces + j);
12824 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12825 GL_AlphaTest(false);
12827 // add to stats if desired
12828 if (r_speeds.integer && !skysurfaces && !depthonly)
12830 r_refdef.stats.entities_surfaces += numsurfacelist;
12831 for (j = 0;j < numsurfacelist;j++)
12832 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12835 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12838 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12840 static texture_t texture;
12841 static msurface_t surface;
12842 const msurface_t *surfacelist = &surface;
12844 // fake enough texture and surface state to render this geometry
12846 texture.update_lastrenderframe = -1; // regenerate this texture
12847 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12848 texture.currentskinframe = skinframe;
12849 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12850 texture.offsetmapping = OFFSETMAPPING_OFF;
12851 texture.offsetscale = 1;
12852 texture.specularscalemod = 1;
12853 texture.specularpowermod = 1;
12855 surface.texture = &texture;
12856 surface.num_triangles = numtriangles;
12857 surface.num_firsttriangle = firsttriangle;
12858 surface.num_vertices = numvertices;
12859 surface.num_firstvertex = firstvertex;
12862 rsurface.texture = R_GetCurrentTexture(surface.texture);
12863 rsurface.uselightmaptexture = false;
12864 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12867 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)
12869 static msurface_t surface;
12870 const msurface_t *surfacelist = &surface;
12872 // fake enough texture and surface state to render this geometry
12874 surface.texture = texture;
12875 surface.num_triangles = numtriangles;
12876 surface.num_firsttriangle = firsttriangle;
12877 surface.num_vertices = numvertices;
12878 surface.num_firstvertex = firstvertex;
12881 rsurface.texture = R_GetCurrentTexture(surface.texture);
12882 rsurface.uselightmaptexture = false;
12883 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);