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_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
80 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
81 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
82 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
83 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
84 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)"};
85 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)"};
86 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
87 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
88 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
89 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
91 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
92 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
93 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
95 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
96 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
97 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
98 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."};
99 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
100 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
101 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
102 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."};
103 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
104 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
105 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
106 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
107 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"};
108 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"};
109 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
110 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
111 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
112 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
113 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"};
115 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
116 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
117 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
118 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
119 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
120 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
121 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
122 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
124 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)"};
125 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"};
127 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
128 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
129 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
130 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
131 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
133 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
134 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
135 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
137 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)"};
138 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
139 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
140 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
141 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
142 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)"};
143 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)"};
144 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)"};
145 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)"};
147 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)"};
148 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
149 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"};
150 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
151 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
152 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
154 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
155 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
156 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
157 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
159 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
160 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
161 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
162 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
163 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
164 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
165 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
167 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
168 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
169 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
170 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)"};
172 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"};
174 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"};
176 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
178 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
179 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
180 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"};
181 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
182 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
183 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
184 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
185 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)"};
187 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
188 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
190 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)"};
192 extern cvar_t v_glslgamma;
194 extern qboolean v_flipped_state;
196 static struct r_bloomstate_s
201 int bloomwidth, bloomheight;
203 int screentexturewidth, screentextureheight;
204 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
206 int bloomtexturewidth, bloomtextureheight;
207 rtexture_t *texture_bloom;
209 // arrays for rendering the screen passes
210 float screentexcoord2f[8];
211 float bloomtexcoord2f[8];
212 float offsettexcoord2f[8];
214 r_viewport_t viewport;
218 r_waterstate_t r_waterstate;
220 /// shadow volume bsp struct with automatically growing nodes buffer
223 rtexture_t *r_texture_blanknormalmap;
224 rtexture_t *r_texture_white;
225 rtexture_t *r_texture_grey128;
226 rtexture_t *r_texture_black;
227 rtexture_t *r_texture_notexture;
228 rtexture_t *r_texture_whitecube;
229 rtexture_t *r_texture_normalizationcube;
230 rtexture_t *r_texture_fogattenuation;
231 rtexture_t *r_texture_fogheighttexture;
232 rtexture_t *r_texture_gammaramps;
233 unsigned int r_texture_gammaramps_serial;
234 //rtexture_t *r_texture_fogintensity;
235 rtexture_t *r_texture_reflectcube;
237 // TODO: hash lookups?
238 typedef struct cubemapinfo_s
245 int r_texture_numcubemaps;
246 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
248 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
249 unsigned int r_numqueries;
250 unsigned int r_maxqueries;
252 typedef struct r_qwskincache_s
254 char name[MAX_QPATH];
255 skinframe_t *skinframe;
259 static r_qwskincache_t *r_qwskincache;
260 static int r_qwskincache_size;
262 /// vertex coordinates for a quad that covers the screen exactly
263 const float r_screenvertex3f[12] =
271 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
274 for (i = 0;i < verts;i++)
285 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
288 for (i = 0;i < verts;i++)
298 // FIXME: move this to client?
301 if (gamemode == GAME_NEHAHRA)
303 Cvar_Set("gl_fogenable", "0");
304 Cvar_Set("gl_fogdensity", "0.2");
305 Cvar_Set("gl_fogred", "0.3");
306 Cvar_Set("gl_foggreen", "0.3");
307 Cvar_Set("gl_fogblue", "0.3");
309 r_refdef.fog_density = 0;
310 r_refdef.fog_red = 0;
311 r_refdef.fog_green = 0;
312 r_refdef.fog_blue = 0;
313 r_refdef.fog_alpha = 1;
314 r_refdef.fog_start = 0;
315 r_refdef.fog_end = 16384;
316 r_refdef.fog_height = 1<<30;
317 r_refdef.fog_fadedepth = 128;
318 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
321 static void R_BuildBlankTextures(void)
323 unsigned char data[4];
324 data[2] = 128; // normal X
325 data[1] = 128; // normal Y
326 data[0] = 255; // normal Z
327 data[3] = 128; // height
328 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
333 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
338 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
343 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
346 static void R_BuildNoTexture(void)
349 unsigned char pix[16][16][4];
350 // this makes a light grey/dark grey checkerboard texture
351 for (y = 0;y < 16;y++)
353 for (x = 0;x < 16;x++)
355 if ((y < 8) ^ (x < 8))
371 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
374 static void R_BuildWhiteCube(void)
376 unsigned char data[6*1*1*4];
377 memset(data, 255, sizeof(data));
378 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
381 static void R_BuildNormalizationCube(void)
385 vec_t s, t, intensity;
388 data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
389 for (side = 0;side < 6;side++)
391 for (y = 0;y < NORMSIZE;y++)
393 for (x = 0;x < NORMSIZE;x++)
395 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
396 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
431 intensity = 127.0f / sqrt(DotProduct(v, v));
432 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
433 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
434 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
435 data[((side*64+y)*64+x)*4+3] = 255;
439 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
443 static void R_BuildFogTexture(void)
447 unsigned char data1[FOGWIDTH][4];
448 //unsigned char data2[FOGWIDTH][4];
451 r_refdef.fogmasktable_start = r_refdef.fog_start;
452 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
453 r_refdef.fogmasktable_range = r_refdef.fogrange;
454 r_refdef.fogmasktable_density = r_refdef.fog_density;
456 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
457 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
459 d = (x * r - r_refdef.fogmasktable_start);
460 if(developer_extra.integer)
461 Con_DPrintf("%f ", d);
463 if (r_fog_exp2.integer)
464 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
466 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
467 if(developer_extra.integer)
468 Con_DPrintf(" : %f ", alpha);
469 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
470 if(developer_extra.integer)
471 Con_DPrintf(" = %f\n", alpha);
472 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
475 for (x = 0;x < FOGWIDTH;x++)
477 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
482 //data2[x][0] = 255 - b;
483 //data2[x][1] = 255 - b;
484 //data2[x][2] = 255 - b;
487 if (r_texture_fogattenuation)
489 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
490 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
494 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
495 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
499 static void R_BuildFogHeightTexture(void)
501 unsigned char *inpixels;
509 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
510 if (r_refdef.fogheighttexturename[0])
511 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
514 r_refdef.fog_height_tablesize = 0;
515 if (r_texture_fogheighttexture)
516 R_FreeTexture(r_texture_fogheighttexture);
517 r_texture_fogheighttexture = NULL;
518 if (r_refdef.fog_height_table2d)
519 Mem_Free(r_refdef.fog_height_table2d);
520 r_refdef.fog_height_table2d = NULL;
521 if (r_refdef.fog_height_table1d)
522 Mem_Free(r_refdef.fog_height_table1d);
523 r_refdef.fog_height_table1d = NULL;
527 r_refdef.fog_height_tablesize = size;
528 r_refdef.fog_height_table1d = Mem_Alloc(r_main_mempool, size * 4);
529 r_refdef.fog_height_table2d = Mem_Alloc(r_main_mempool, size * size * 4);
530 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
532 // LordHavoc: now the magic - what is that table2d for? it is a cooked
533 // average fog color table accounting for every fog layer between a point
534 // and the camera. (Note: attenuation is handled separately!)
535 for (y = 0;y < size;y++)
537 for (x = 0;x < size;x++)
543 for (j = x;j <= y;j++)
545 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
551 for (j = x;j >= y;j--)
553 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
558 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
559 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
560 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
561 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
564 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
567 //=======================================================================================================================================================
569 static const char *builtinshaderstring =
570 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
571 "// written by Forest 'LordHavoc' Hale\n"
572 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
574 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
577 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
578 "#define USELIGHTMAP\n"
580 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
581 "#define USEEYEVECTOR\n"
584 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
585 "# extension GL_ARB_texture_rectangle : enable\n"
588 "#ifdef USESHADOWMAP2D\n"
589 "# ifdef GL_EXT_gpu_shader4\n"
590 "# extension GL_EXT_gpu_shader4 : enable\n"
592 "# ifdef GL_ARB_texture_gather\n"
593 "# extension GL_ARB_texture_gather : enable\n"
595 "# ifdef GL_AMD_texture_texture4\n"
596 "# extension GL_AMD_texture_texture4 : enable\n"
601 "#ifdef USESHADOWMAPCUBE\n"
602 "# extension GL_EXT_gpu_shader4 : enable\n"
605 "//#ifdef USESHADOWSAMPLER\n"
606 "//# extension GL_ARB_shadow : enable\n"
609 "//#ifdef __GLSL_CG_DATA_TYPES\n"
610 "//# define myhalf half\n"
611 "//# define myhalf2 half2\n"
612 "//# define myhalf3 half3\n"
613 "//# define myhalf4 half4\n"
615 "# define myhalf float\n"
616 "# define myhalf2 vec2\n"
617 "# define myhalf3 vec3\n"
618 "# define myhalf4 vec4\n"
621 "#ifdef VERTEX_SHADER\n"
622 "uniform mat4 ModelViewProjectionMatrix;\n"
625 "#ifdef MODE_DEPTH_OR_SHADOW\n"
626 "#ifdef VERTEX_SHADER\n"
629 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
632 "#else // !MODE_DEPTH_ORSHADOW\n"
637 "#ifdef MODE_SHOWDEPTH\n"
638 "#ifdef VERTEX_SHADER\n"
641 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
642 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
646 "#ifdef FRAGMENT_SHADER\n"
649 " gl_FragColor = gl_Color;\n"
652 "#else // !MODE_SHOWDEPTH\n"
657 "#ifdef MODE_POSTPROCESS\n"
658 "varying vec2 TexCoord1;\n"
659 "varying vec2 TexCoord2;\n"
661 "#ifdef VERTEX_SHADER\n"
664 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
665 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
667 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
672 "#ifdef FRAGMENT_SHADER\n"
673 "uniform sampler2D Texture_First;\n"
675 "uniform sampler2D Texture_Second;\n"
677 "#ifdef USEGAMMARAMPS\n"
678 "uniform sampler2D Texture_GammaRamps;\n"
680 "#ifdef USESATURATION\n"
681 "uniform float Saturation;\n"
683 "#ifdef USEVIEWTINT\n"
684 "uniform vec4 ViewTintColor;\n"
686 "//uncomment these if you want to use them:\n"
687 "uniform vec4 UserVec1;\n"
688 "uniform vec4 UserVec2;\n"
689 "// uniform vec4 UserVec3;\n"
690 "// uniform vec4 UserVec4;\n"
691 "// uniform float ClientTime;\n"
692 "uniform vec2 PixelSize;\n"
695 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
697 " gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
699 "#ifdef USEVIEWTINT\n"
700 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
703 "#ifdef USEPOSTPROCESSING\n"
704 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
705 "// 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"
706 " float sobel = 1.0;\n"
707 " // vec2 ts = textureSize(Texture_First, 0);\n"
708 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
709 " vec2 px = PixelSize;\n"
710 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
711 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
712 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
713 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
714 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
715 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
716 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
717 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
718 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
719 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
720 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
721 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
722 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
723 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
724 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
725 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
726 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
727 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
728 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
729 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
730 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
731 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
732 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
733 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
734 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
735 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
736 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
737 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
738 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
739 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
740 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
741 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
744 "#ifdef USESATURATION\n"
745 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
746 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
747 " // 'vampire sight' effect, wheres red is compensated\n"
748 " #ifdef SATURATION_REDCOMPENSATE\n"
749 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
750 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
751 " gl_FragColor.r += rboost;\n"
753 " // normal desaturation\n"
754 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
755 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
759 "#ifdef USEGAMMARAMPS\n"
760 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
761 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
762 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
766 "#else // !MODE_POSTPROCESS\n"
771 "#ifdef MODE_GENERIC\n"
772 "#ifdef USEDIFFUSE\n"
773 "varying vec2 TexCoord1;\n"
775 "#ifdef USESPECULAR\n"
776 "varying vec2 TexCoord2;\n"
778 "#ifdef VERTEX_SHADER\n"
781 " gl_FrontColor = gl_Color;\n"
782 "#ifdef USEDIFFUSE\n"
783 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
785 "#ifdef USESPECULAR\n"
786 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
788 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
792 "#ifdef FRAGMENT_SHADER\n"
793 "#ifdef USEDIFFUSE\n"
794 "uniform sampler2D Texture_First;\n"
796 "#ifdef USESPECULAR\n"
797 "uniform sampler2D Texture_Second;\n"
802 " gl_FragColor = gl_Color;\n"
803 "#ifdef USEDIFFUSE\n"
804 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
807 "#ifdef USESPECULAR\n"
808 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
809 "# ifdef USECOLORMAPPING\n"
810 " gl_FragColor *= tex2;\n"
813 " gl_FragColor += tex2;\n"
815 "# ifdef USEVERTEXTEXTUREBLEND\n"
816 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
821 "#else // !MODE_GENERIC\n"
826 "#ifdef MODE_BLOOMBLUR\n"
827 "varying TexCoord;\n"
828 "#ifdef VERTEX_SHADER\n"
831 " gl_FrontColor = gl_Color;\n"
832 " TexCoord = gl_MultiTexCoord0.xy;\n"
833 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
837 "#ifdef FRAGMENT_SHADER\n"
838 "uniform sampler2D Texture_First;\n"
839 "uniform vec4 BloomBlur_Parameters;\n"
844 " vec2 tc = TexCoord;\n"
845 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
846 " tc += BloomBlur_Parameters.xy;\n"
847 " for (i = 1;i < SAMPLES;i++)\n"
849 " color += texture2D(Texture_First, tc).rgb;\n"
850 " tc += BloomBlur_Parameters.xy;\n"
852 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
855 "#else // !MODE_BLOOMBLUR\n"
856 "#ifdef MODE_REFRACTION\n"
857 "varying vec2 TexCoord;\n"
858 "varying vec4 ModelViewProjectionPosition;\n"
859 "uniform mat4 TexMatrix;\n"
860 "#ifdef VERTEX_SHADER\n"
864 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
865 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
866 " ModelViewProjectionPosition = gl_Position;\n"
870 "#ifdef FRAGMENT_SHADER\n"
871 "uniform sampler2D Texture_Normal;\n"
872 "uniform sampler2D Texture_Refraction;\n"
873 "uniform sampler2D Texture_Reflection;\n"
875 "uniform vec4 DistortScaleRefractReflect;\n"
876 "uniform vec4 ScreenScaleRefractReflect;\n"
877 "uniform vec4 ScreenCenterRefractReflect;\n"
878 "uniform vec4 RefractColor;\n"
879 "uniform vec4 ReflectColor;\n"
880 "uniform float ReflectFactor;\n"
881 "uniform float ReflectOffset;\n"
885 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
886 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
887 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
888 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
889 " // FIXME temporary hack to detect the case that the reflection\n"
890 " // gets blackened at edges due to leaving the area that contains actual\n"
892 " // Remove this 'ack once we have a better way to stop this thing from\n"
894 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
895 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
896 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
897 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
898 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
899 " gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
902 "#else // !MODE_REFRACTION\n"
907 "#ifdef MODE_WATER\n"
908 "varying vec2 TexCoord;\n"
909 "varying vec3 EyeVector;\n"
910 "varying vec4 ModelViewProjectionPosition;\n"
911 "#ifdef VERTEX_SHADER\n"
912 "uniform vec3 EyePosition;\n"
913 "uniform mat4 TexMatrix;\n"
917 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
918 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
919 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
920 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
921 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
922 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
923 " ModelViewProjectionPosition = gl_Position;\n"
927 "#ifdef FRAGMENT_SHADER\n"
928 "uniform sampler2D Texture_Normal;\n"
929 "uniform sampler2D Texture_Refraction;\n"
930 "uniform sampler2D Texture_Reflection;\n"
932 "uniform vec4 DistortScaleRefractReflect;\n"
933 "uniform vec4 ScreenScaleRefractReflect;\n"
934 "uniform vec4 ScreenCenterRefractReflect;\n"
935 "uniform vec4 RefractColor;\n"
936 "uniform vec4 ReflectColor;\n"
937 "uniform float ReflectFactor;\n"
938 "uniform float ReflectOffset;\n"
939 "uniform float ClientTime;\n"
940 "#ifdef USENORMALMAPSCROLLBLEND\n"
941 "uniform vec2 NormalmapScrollBlend;\n"
946 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
947 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
948 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
949 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
950 " // slight water animation via 2 layer scrolling (todo: tweak)\n"
951 " #ifdef USENORMALMAPSCROLLBLEND\n"
952 " vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
953 " normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
954 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
956 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
958 " // FIXME temporary hack to detect the case that the reflection\n"
959 " // gets blackened at edges due to leaving the area that contains actual\n"
961 " // Remove this 'ack once we have a better way to stop this thing from\n"
963 " float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
964 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
965 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
966 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
967 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
968 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
969 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
970 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
971 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
972 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
973 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
974 " gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
975 " gl_FragColor.a = f1 + 0.5;\n"
978 "#else // !MODE_WATER\n"
983 "// common definitions between vertex shader and fragment shader:\n"
985 "varying vec2 TexCoord;\n"
986 "#ifdef USEVERTEXTEXTUREBLEND\n"
987 "varying vec2 TexCoord2;\n"
989 "#ifdef USELIGHTMAP\n"
990 "varying vec2 TexCoordLightmap;\n"
993 "#ifdef MODE_LIGHTSOURCE\n"
994 "varying vec3 CubeVector;\n"
997 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
998 "varying vec3 LightVector;\n"
1001 "#ifdef USEEYEVECTOR\n"
1002 "varying vec3 EyeVector;\n"
1005 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1008 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1009 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1010 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1011 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1014 "#ifdef USEREFLECTION\n"
1015 "varying vec4 ModelViewProjectionPosition;\n"
1017 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1018 "uniform vec3 LightPosition;\n"
1019 "varying vec4 ModelViewPosition;\n"
1022 "#ifdef MODE_LIGHTSOURCE\n"
1023 "uniform vec3 LightPosition;\n"
1025 "uniform vec3 EyePosition;\n"
1026 "#ifdef MODE_LIGHTDIRECTION\n"
1027 "uniform vec3 LightDir;\n"
1029 "uniform vec4 FogPlane;\n"
1031 "#ifdef USESHADOWMAPORTHO\n"
1032 "varying vec3 ShadowMapTC;\n"
1039 "// 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"
1041 "// fragment shader specific:\n"
1042 "#ifdef FRAGMENT_SHADER\n"
1044 "uniform sampler2D Texture_Normal;\n"
1045 "uniform sampler2D Texture_Color;\n"
1046 "uniform sampler2D Texture_Gloss;\n"
1048 "uniform sampler2D Texture_Glow;\n"
1050 "#ifdef USEVERTEXTEXTUREBLEND\n"
1051 "uniform sampler2D Texture_SecondaryNormal;\n"
1052 "uniform sampler2D Texture_SecondaryColor;\n"
1053 "uniform sampler2D Texture_SecondaryGloss;\n"
1055 "uniform sampler2D Texture_SecondaryGlow;\n"
1058 "#ifdef USECOLORMAPPING\n"
1059 "uniform sampler2D Texture_Pants;\n"
1060 "uniform sampler2D Texture_Shirt;\n"
1063 "#ifdef USEFOGHEIGHTTEXTURE\n"
1064 "uniform sampler2D Texture_FogHeightTexture;\n"
1066 "uniform sampler2D Texture_FogMask;\n"
1068 "#ifdef USELIGHTMAP\n"
1069 "uniform sampler2D Texture_Lightmap;\n"
1071 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1072 "uniform sampler2D Texture_Deluxemap;\n"
1074 "#ifdef USEREFLECTION\n"
1075 "uniform sampler2D Texture_Reflection;\n"
1078 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1079 "uniform sampler2D Texture_ScreenDepth;\n"
1080 "uniform sampler2D Texture_ScreenNormalMap;\n"
1082 "#ifdef USEDEFERREDLIGHTMAP\n"
1083 "uniform sampler2D Texture_ScreenDiffuse;\n"
1084 "uniform sampler2D Texture_ScreenSpecular;\n"
1087 "uniform myhalf3 Color_Pants;\n"
1088 "uniform myhalf3 Color_Shirt;\n"
1089 "uniform myhalf3 FogColor;\n"
1092 "uniform float FogRangeRecip;\n"
1093 "uniform float FogPlaneViewDist;\n"
1094 "uniform float FogHeightFade;\n"
1095 "vec3 FogVertex(vec3 surfacecolor)\n"
1097 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1098 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1100 "#ifdef USEFOGHEIGHTTEXTURE\n"
1101 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1102 " fogfrac = fogheightpixel.a;\n"
1103 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1105 "# ifdef USEFOGOUTSIDE\n"
1106 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1108 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1110 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1115 "#ifdef USEOFFSETMAPPING\n"
1116 "uniform float OffsetMapping_Scale;\n"
1117 "vec2 OffsetMapping(vec2 TexCoord)\n"
1119 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1120 " // 14 sample relief mapping: linear search and then binary search\n"
1121 " // this basically steps forward a small amount repeatedly until it finds\n"
1122 " // itself inside solid, then jitters forward and back using decreasing\n"
1123 " // amounts to find the impact\n"
1124 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1125 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1126 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1127 " vec3 RT = vec3(TexCoord, 1);\n"
1128 " OffsetVector *= 0.1;\n"
1129 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1130 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1131 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1132 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1133 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1134 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1135 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1136 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1137 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1138 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1139 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1140 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1141 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1142 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1145 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1146 " // this basically moves forward the full distance, and then backs up based\n"
1147 " // on height of samples\n"
1148 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1149 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1150 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1151 " TexCoord += OffsetVector;\n"
1152 " OffsetVector *= 0.333;\n"
1153 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1154 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1155 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1156 " return TexCoord;\n"
1159 "#endif // USEOFFSETMAPPING\n"
1161 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1162 "uniform sampler2D Texture_Attenuation;\n"
1163 "uniform samplerCube Texture_Cube;\n"
1166 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1168 "#ifdef USESHADOWMAPRECT\n"
1169 "# ifdef USESHADOWSAMPLER\n"
1170 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1172 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1176 "#ifdef USESHADOWMAP2D\n"
1177 "# ifdef USESHADOWSAMPLER\n"
1178 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1180 "uniform sampler2D Texture_ShadowMap2D;\n"
1184 "#ifdef USESHADOWMAPVSDCT\n"
1185 "uniform samplerCube Texture_CubeProjection;\n"
1188 "#ifdef USESHADOWMAPCUBE\n"
1189 "# ifdef USESHADOWSAMPLER\n"
1190 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1192 "uniform samplerCube Texture_ShadowMapCube;\n"
1196 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1197 "uniform vec2 ShadowMap_TextureScale;\n"
1198 "uniform vec4 ShadowMap_Parameters;\n"
1201 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1202 "# ifdef USESHADOWMAPORTHO\n"
1203 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1205 "# ifdef USESHADOWMAPVSDCT\n"
1206 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1208 " vec3 adir = abs(dir);\n"
1209 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1210 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1211 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1214 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1216 " vec3 adir = abs(dir);\n"
1217 " float ma = adir.z;\n"
1218 " vec4 proj = vec4(dir, 2.5);\n"
1219 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1220 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1221 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1222 " 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"
1226 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1228 "#ifdef USESHADOWMAPCUBE\n"
1229 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1231 " vec3 adir = abs(dir);\n"
1232 " return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1236 "# ifdef USESHADOWMAPRECT\n"
1237 "float ShadowMapCompare(vec3 dir)\n"
1239 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1241 "# ifdef USESHADOWSAMPLER\n"
1243 "# ifdef USESHADOWMAPPCF\n"
1244 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1245 " 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"
1247 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1252 "# ifdef USESHADOWMAPPCF\n"
1253 "# if USESHADOWMAPPCF > 1\n"
1254 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1255 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1256 " 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"
1257 " 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"
1258 " 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"
1259 " 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"
1260 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1261 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1263 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1264 " vec2 offset = fract(shadowmaptc.xy);\n"
1265 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1266 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1267 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1268 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1269 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1272 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1276 "# ifdef USESHADOWMAPORTHO\n"
1277 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1284 "# ifdef USESHADOWMAP2D\n"
1285 "float ShadowMapCompare(vec3 dir)\n"
1287 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1290 "# ifdef USESHADOWSAMPLER\n"
1291 "# ifdef USESHADOWMAPPCF\n"
1292 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1293 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1294 " 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"
1296 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1299 "# ifdef USESHADOWMAPPCF\n"
1300 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1301 "# ifdef GL_ARB_texture_gather\n"
1302 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1304 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1306 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1307 "# if USESHADOWMAPPCF > 1\n"
1308 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1309 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1310 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1311 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1312 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1313 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1314 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1315 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1316 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1317 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1318 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1319 " locols.yz += group2.ab;\n"
1320 " hicols.yz += group8.rg;\n"
1321 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1322 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1323 " mix(locols, hicols, offset.y);\n"
1324 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1325 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1326 " f = dot(cols, vec4(1.0/25.0));\n"
1328 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1329 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1330 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1331 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1332 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1333 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1334 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1337 "# ifdef GL_EXT_gpu_shader4\n"
1338 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1340 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1342 "# if USESHADOWMAPPCF > 1\n"
1343 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1344 " center *= ShadowMap_TextureScale;\n"
1345 " 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"
1346 " 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"
1347 " 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"
1348 " 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"
1349 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1350 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1352 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1353 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1354 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1355 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1356 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1357 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1361 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1364 "# ifdef USESHADOWMAPORTHO\n"
1365 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1372 "# ifdef USESHADOWMAPCUBE\n"
1373 "float ShadowMapCompare(vec3 dir)\n"
1375 " // apply depth texture cubemap as light filter\n"
1376 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1378 "# ifdef USESHADOWSAMPLER\n"
1379 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1381 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1386 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1387 "#endif // FRAGMENT_SHADER\n"
1392 "#ifdef MODE_DEFERREDGEOMETRY\n"
1393 "#ifdef VERTEX_SHADER\n"
1394 "uniform mat4 TexMatrix;\n"
1395 "#ifdef USEVERTEXTEXTUREBLEND\n"
1396 "uniform mat4 BackgroundTexMatrix;\n"
1398 "uniform mat4 ModelViewMatrix;\n"
1401 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1402 "#ifdef USEVERTEXTEXTUREBLEND\n"
1403 " gl_FrontColor = gl_Color;\n"
1404 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1407 " // transform unnormalized eye direction into tangent space\n"
1408 "#ifdef USEOFFSETMAPPING\n"
1409 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1410 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1411 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1412 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1415 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1416 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1417 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1418 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1420 "#endif // VERTEX_SHADER\n"
1422 "#ifdef FRAGMENT_SHADER\n"
1425 "#ifdef USEOFFSETMAPPING\n"
1426 " // apply offsetmapping\n"
1427 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1428 "#define TexCoord TexCoordOffset\n"
1431 "#ifdef USEALPHAKILL\n"
1432 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1436 "#ifdef USEVERTEXTEXTUREBLEND\n"
1437 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1438 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1439 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1440 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1443 "#ifdef USEVERTEXTEXTUREBLEND\n"
1444 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1445 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1447 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1448 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1451 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1453 "#endif // FRAGMENT_SHADER\n"
1454 "#else // !MODE_DEFERREDGEOMETRY\n"
1459 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1460 "#ifdef VERTEX_SHADER\n"
1461 "uniform mat4 ModelViewMatrix;\n"
1464 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1465 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1467 "#endif // VERTEX_SHADER\n"
1469 "#ifdef FRAGMENT_SHADER\n"
1470 "uniform mat4 ViewToLight;\n"
1471 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1472 "uniform vec2 ScreenToDepth;\n"
1473 "uniform myhalf3 DeferredColor_Ambient;\n"
1474 "uniform myhalf3 DeferredColor_Diffuse;\n"
1475 "#ifdef USESPECULAR\n"
1476 "uniform myhalf3 DeferredColor_Specular;\n"
1477 "uniform myhalf SpecularPower;\n"
1479 "uniform myhalf2 PixelToScreenTexCoord;\n"
1482 " // calculate viewspace pixel position\n"
1483 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1485 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1486 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1487 " // decode viewspace pixel normal\n"
1488 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1489 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1490 " // surfacenormal = pixel normal in viewspace\n"
1491 " // LightVector = pixel to light in viewspace\n"
1492 " // CubeVector = position in lightspace\n"
1493 " // eyevector = pixel to view in viewspace\n"
1494 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1495 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1496 "#ifdef USEDIFFUSE\n"
1497 " // calculate diffuse shading\n"
1498 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1499 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1501 "#ifdef USESPECULAR\n"
1502 " // calculate directional shading\n"
1503 " vec3 eyevector = position * -1.0;\n"
1504 "# ifdef USEEXACTSPECULARMATH\n"
1505 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1507 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1508 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1512 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1513 " fade *= ShadowMapCompare(CubeVector);\n"
1516 "#ifdef USEDIFFUSE\n"
1517 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1519 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1521 "#ifdef USESPECULAR\n"
1522 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1524 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1527 "# ifdef USECUBEFILTER\n"
1528 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1529 " gl_FragData[0].rgb *= cubecolor;\n"
1530 " gl_FragData[1].rgb *= cubecolor;\n"
1533 "#endif // FRAGMENT_SHADER\n"
1534 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1539 "#ifdef VERTEX_SHADER\n"
1540 "uniform mat4 TexMatrix;\n"
1541 "#ifdef USEVERTEXTEXTUREBLEND\n"
1542 "uniform mat4 BackgroundTexMatrix;\n"
1544 "#ifdef MODE_LIGHTSOURCE\n"
1545 "uniform mat4 ModelToLight;\n"
1547 "#ifdef USESHADOWMAPORTHO\n"
1548 "uniform mat4 ShadowMapMatrix;\n"
1552 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1553 " gl_FrontColor = gl_Color;\n"
1555 " // copy the surface texcoord\n"
1556 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1557 "#ifdef USEVERTEXTEXTUREBLEND\n"
1558 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1560 "#ifdef USELIGHTMAP\n"
1561 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1564 "#ifdef MODE_LIGHTSOURCE\n"
1565 " // transform vertex position into light attenuation/cubemap space\n"
1566 " // (-1 to +1 across the light box)\n"
1567 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1569 "# ifdef USEDIFFUSE\n"
1570 " // transform unnormalized light direction into tangent space\n"
1571 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1572 " // normalize it per pixel)\n"
1573 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1574 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1575 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1576 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1580 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1581 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1582 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1583 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1586 " // transform unnormalized eye direction into tangent space\n"
1587 "#ifdef USEEYEVECTOR\n"
1588 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1589 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1590 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1591 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1595 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1596 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1599 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1600 " VectorS = gl_MultiTexCoord1.xyz;\n"
1601 " VectorT = gl_MultiTexCoord2.xyz;\n"
1602 " VectorR = gl_MultiTexCoord3.xyz;\n"
1605 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1606 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1608 "#ifdef USESHADOWMAPORTHO\n"
1609 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1612 "#ifdef USEREFLECTION\n"
1613 " ModelViewProjectionPosition = gl_Position;\n"
1616 "#endif // VERTEX_SHADER\n"
1621 "#ifdef FRAGMENT_SHADER\n"
1622 "#ifdef USEDEFERREDLIGHTMAP\n"
1623 "uniform myhalf2 PixelToScreenTexCoord;\n"
1624 "uniform myhalf3 DeferredMod_Diffuse;\n"
1625 "uniform myhalf3 DeferredMod_Specular;\n"
1627 "uniform myhalf3 Color_Ambient;\n"
1628 "uniform myhalf3 Color_Diffuse;\n"
1629 "uniform myhalf3 Color_Specular;\n"
1630 "uniform myhalf SpecularPower;\n"
1632 "uniform myhalf3 Color_Glow;\n"
1634 "uniform myhalf Alpha;\n"
1635 "#ifdef USEREFLECTION\n"
1636 "uniform vec4 DistortScaleRefractReflect;\n"
1637 "uniform vec4 ScreenScaleRefractReflect;\n"
1638 "uniform vec4 ScreenCenterRefractReflect;\n"
1639 "uniform myhalf4 ReflectColor;\n"
1641 "#ifdef USEREFLECTCUBE\n"
1642 "uniform mat4 ModelToReflectCube;\n"
1643 "uniform sampler2D Texture_ReflectMask;\n"
1644 "uniform samplerCube Texture_ReflectCube;\n"
1646 "#ifdef MODE_LIGHTDIRECTION\n"
1647 "uniform myhalf3 LightColor;\n"
1649 "#ifdef MODE_LIGHTSOURCE\n"
1650 "uniform myhalf3 LightColor;\n"
1654 "#ifdef USEOFFSETMAPPING\n"
1655 " // apply offsetmapping\n"
1656 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1657 "#define TexCoord TexCoordOffset\n"
1660 " // combine the diffuse textures (base, pants, shirt)\n"
1661 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1662 "#ifdef USEALPHAKILL\n"
1663 " if (color.a < 0.5)\n"
1666 " color.a *= Alpha;\n"
1667 "#ifdef USECOLORMAPPING\n"
1668 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1670 "#ifdef USEVERTEXTEXTUREBLEND\n"
1671 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1672 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1673 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1674 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1676 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1679 " // get the surface normal\n"
1680 "#ifdef USEVERTEXTEXTUREBLEND\n"
1681 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1683 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1686 " // get the material colors\n"
1687 " myhalf3 diffusetex = color.rgb;\n"
1688 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1689 "# ifdef USEVERTEXTEXTUREBLEND\n"
1690 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1692 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1696 "#ifdef USEREFLECTCUBE\n"
1697 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1698 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1699 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1700 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1706 "#ifdef MODE_LIGHTSOURCE\n"
1707 " // light source\n"
1708 "#ifdef USEDIFFUSE\n"
1709 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1710 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1711 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1712 "#ifdef USESPECULAR\n"
1713 "#ifdef USEEXACTSPECULARMATH\n"
1714 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1716 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1717 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1719 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1722 " color.rgb = diffusetex * Color_Ambient;\n"
1724 " color.rgb *= LightColor;\n"
1725 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1726 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1727 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1729 "# ifdef USECUBEFILTER\n"
1730 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1732 "#endif // MODE_LIGHTSOURCE\n"
1737 "#ifdef MODE_LIGHTDIRECTION\n"
1739 "#ifdef USEDIFFUSE\n"
1740 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1742 "#define lightcolor LightColor\n"
1743 "#endif // MODE_LIGHTDIRECTION\n"
1744 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1746 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1747 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1748 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1749 " // convert modelspace light vector to tangentspace\n"
1750 " myhalf3 lightnormal;\n"
1751 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1752 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1753 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1754 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1755 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1756 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1757 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1758 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1759 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1760 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1761 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1762 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1763 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1764 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1765 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1767 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1768 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1769 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1775 "#ifdef MODE_FAKELIGHT\n"
1777 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1778 "myhalf3 lightcolor = myhalf3(1.0);\n"
1779 "#endif // MODE_FAKELIGHT\n"
1784 "#ifdef MODE_LIGHTMAP\n"
1785 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1786 "#endif // MODE_LIGHTMAP\n"
1787 "#ifdef MODE_VERTEXCOLOR\n"
1788 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1789 "#endif // MODE_VERTEXCOLOR\n"
1790 "#ifdef MODE_FLATCOLOR\n"
1791 " color.rgb = diffusetex * Color_Ambient;\n"
1792 "#endif // MODE_FLATCOLOR\n"
1798 "# ifdef USEDIFFUSE\n"
1799 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1800 "# ifdef USESPECULAR\n"
1801 "# ifdef USEEXACTSPECULARMATH\n"
1802 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1804 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1805 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1807 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1809 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1812 " color.rgb = diffusetex * Color_Ambient;\n"
1816 "#ifdef USESHADOWMAPORTHO\n"
1817 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1820 "#ifdef USEDEFERREDLIGHTMAP\n"
1821 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1822 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1823 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1827 "#ifdef USEVERTEXTEXTUREBLEND\n"
1828 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1830 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1835 " color.rgb = FogVertex(color.rgb);\n"
1838 " // 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"
1839 "#ifdef USEREFLECTION\n"
1840 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1841 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1842 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1843 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1844 " // FIXME temporary hack to detect the case that the reflection\n"
1845 " // gets blackened at edges due to leaving the area that contains actual\n"
1847 " // Remove this 'ack once we have a better way to stop this thing from\n"
1849 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1850 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1851 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1852 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1853 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1854 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1857 " gl_FragColor = vec4(color);\n"
1859 "#endif // FRAGMENT_SHADER\n"
1861 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1862 "#endif // !MODE_DEFERREDGEOMETRY\n"
1863 "#endif // !MODE_WATER\n"
1864 "#endif // !MODE_REFRACTION\n"
1865 "#endif // !MODE_BLOOMBLUR\n"
1866 "#endif // !MODE_GENERIC\n"
1867 "#endif // !MODE_POSTPROCESS\n"
1868 "#endif // !MODE_SHOWDEPTH\n"
1869 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1873 =========================================================================================================================================================
1877 =========================================================================================================================================================
1881 =========================================================================================================================================================
1885 =========================================================================================================================================================
1889 =========================================================================================================================================================
1893 =========================================================================================================================================================
1897 =========================================================================================================================================================
1900 const char *builtincgshaderstring =
1901 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1902 "// written by Forest 'LordHavoc' Hale\n"
1903 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1905 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1906 "#if defined(USEREFLECTION)\n"
1907 "#undef USESHADOWMAPORTHO\n"
1910 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1913 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1914 "#define USELIGHTMAP\n"
1916 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1917 "#define USEEYEVECTOR\n"
1920 "#ifdef FRAGMENT_SHADER\n"
1921 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1924 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1925 "#ifdef VERTEX_SHADER\n"
1928 "float4 gl_Vertex : POSITION,\n"
1929 "uniform float4x4 ModelViewProjectionMatrix,\n"
1930 "out float4 gl_Position : POSITION\n"
1933 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1936 "#else // !MODE_DEPTH_ORSHADOW\n"
1941 "#ifdef MODE_SHOWDEPTH\n"
1942 "#ifdef VERTEX_SHADER\n"
1945 "float4 gl_Vertex : POSITION,\n"
1946 "uniform float4x4 ModelViewProjectionMatrix,\n"
1947 "out float4 gl_Position : POSITION,\n"
1948 "out float4 gl_FrontColor : COLOR0\n"
1951 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1952 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1956 "#ifdef FRAGMENT_SHADER\n"
1959 "float4 gl_FrontColor : COLOR0,\n"
1960 "out float4 gl_FragColor : COLOR\n"
1963 " gl_FragColor = gl_FrontColor;\n"
1966 "#else // !MODE_SHOWDEPTH\n"
1971 "#ifdef MODE_POSTPROCESS\n"
1973 "#ifdef VERTEX_SHADER\n"
1976 "float4 gl_Vertex : POSITION,\n"
1977 "uniform float4x4 ModelViewProjectionMatrix,\n"
1978 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1979 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1980 "out float4 gl_Position : POSITION,\n"
1981 "out float2 TexCoord1 : TEXCOORD0,\n"
1982 "out float2 TexCoord2 : TEXCOORD1\n"
1985 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1986 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1988 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1993 "#ifdef FRAGMENT_SHADER\n"
1996 "float2 TexCoord1 : TEXCOORD0,\n"
1997 "float2 TexCoord2 : TEXCOORD1,\n"
1998 "uniform sampler2D Texture_First,\n"
2000 "uniform sampler2D Texture_Second,\n"
2002 "#ifdef USEGAMMARAMPS\n"
2003 "uniform sampler2D Texture_GammaRamps,\n"
2005 "#ifdef USESATURATION\n"
2006 "uniform float Saturation,\n"
2008 "#ifdef USEVIEWTINT\n"
2009 "uniform float4 ViewTintColor,\n"
2011 "uniform float4 UserVec1,\n"
2012 "uniform float4 UserVec2,\n"
2013 "uniform float4 UserVec3,\n"
2014 "uniform float4 UserVec4,\n"
2015 "uniform float ClientTime,\n"
2016 "uniform float2 PixelSize,\n"
2017 "out float4 gl_FragColor : COLOR\n"
2020 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2022 " gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
2024 "#ifdef USEVIEWTINT\n"
2025 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2028 "#ifdef USEPOSTPROCESSING\n"
2029 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2030 "// 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"
2031 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2032 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2033 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2034 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2035 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2036 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
2039 "#ifdef USESATURATION\n"
2040 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2041 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2042 " // 'vampire sight' effect, wheres red is compensated\n"
2043 " #ifdef SATURATION_REDCOMPENSATE\n"
2044 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2045 " gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2046 " gl_FragColor.r += r;\n"
2048 " // normal desaturation\n"
2049 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2050 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2054 "#ifdef USEGAMMARAMPS\n"
2055 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2056 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2057 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2061 "#else // !MODE_POSTPROCESS\n"
2066 "#ifdef MODE_GENERIC\n"
2067 "#ifdef VERTEX_SHADER\n"
2070 "float4 gl_Vertex : POSITION,\n"
2071 "uniform float4x4 ModelViewProjectionMatrix,\n"
2072 "float4 gl_Color : COLOR0,\n"
2073 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2074 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2075 "out float4 gl_Position : POSITION,\n"
2076 "out float4 gl_FrontColor : COLOR,\n"
2077 "out float2 TexCoord1 : TEXCOORD0,\n"
2078 "out float2 TexCoord2 : TEXCOORD1\n"
2081 " gl_FrontColor = gl_Color;\n"
2082 "#ifdef USEDIFFUSE\n"
2083 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2085 "#ifdef USESPECULAR\n"
2086 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2088 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2092 "#ifdef FRAGMENT_SHADER\n"
2096 "float4 gl_FrontColor : COLOR,\n"
2097 "float2 TexCoord1 : TEXCOORD0,\n"
2098 "float2 TexCoord2 : TEXCOORD1,\n"
2099 "#ifdef USEDIFFUSE\n"
2100 "uniform sampler2D Texture_First,\n"
2102 "#ifdef USESPECULAR\n"
2103 "uniform sampler2D Texture_Second,\n"
2105 "out float4 gl_FragColor : COLOR\n"
2108 " gl_FragColor = gl_FrontColor;\n"
2109 "#ifdef USEDIFFUSE\n"
2110 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2113 "#ifdef USESPECULAR\n"
2114 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2115 "# ifdef USECOLORMAPPING\n"
2116 " gl_FragColor *= tex2;\n"
2119 " gl_FragColor += tex2;\n"
2121 "# ifdef USEVERTEXTEXTUREBLEND\n"
2122 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2127 "#else // !MODE_GENERIC\n"
2132 "#ifdef MODE_BLOOMBLUR\n"
2133 "#ifdef VERTEX_SHADER\n"
2136 "float4 gl_Vertex : POSITION,\n"
2137 "uniform float4x4 ModelViewProjectionMatrix,\n"
2138 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2139 "out float4 gl_Position : POSITION,\n"
2140 "out float2 TexCoord : TEXCOORD0\n"
2143 " TexCoord = gl_MultiTexCoord0.xy;\n"
2144 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2148 "#ifdef FRAGMENT_SHADER\n"
2152 "float2 TexCoord : TEXCOORD0,\n"
2153 "uniform sampler2D Texture_First,\n"
2154 "uniform float4 BloomBlur_Parameters,\n"
2155 "out float4 gl_FragColor : COLOR\n"
2159 " float2 tc = TexCoord;\n"
2160 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2161 " tc += BloomBlur_Parameters.xy;\n"
2162 " for (i = 1;i < SAMPLES;i++)\n"
2164 " color += tex2D(Texture_First, tc).rgb;\n"
2165 " tc += BloomBlur_Parameters.xy;\n"
2167 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2170 "#else // !MODE_BLOOMBLUR\n"
2171 "#ifdef MODE_REFRACTION\n"
2172 "#ifdef VERTEX_SHADER\n"
2175 "float4 gl_Vertex : POSITION,\n"
2176 "uniform float4x4 ModelViewProjectionMatrix,\n"
2177 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2178 "uniform float4x4 TexMatrix,\n"
2179 "uniform float3 EyePosition,\n"
2180 "out float4 gl_Position : POSITION,\n"
2181 "out float2 TexCoord : TEXCOORD0,\n"
2182 "out float3 EyeVector : TEXCOORD1,\n"
2183 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2186 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2187 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2188 " ModelViewProjectionPosition = gl_Position;\n"
2192 "#ifdef FRAGMENT_SHADER\n"
2195 "float2 TexCoord : TEXCOORD0,\n"
2196 "float3 EyeVector : TEXCOORD1,\n"
2197 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2198 "uniform sampler2D Texture_Normal,\n"
2199 "uniform sampler2D Texture_Refraction,\n"
2200 "uniform sampler2D Texture_Reflection,\n"
2201 "uniform float4 DistortScaleRefractReflect,\n"
2202 "uniform float4 ScreenScaleRefractReflect,\n"
2203 "uniform float4 ScreenCenterRefractReflect,\n"
2204 "uniform float4 RefractColor,\n"
2205 "out float4 gl_FragColor : COLOR\n"
2208 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2209 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2210 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2211 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2212 " // FIXME temporary hack to detect the case that the reflection\n"
2213 " // gets blackened at edges due to leaving the area that contains actual\n"
2215 " // Remove this 'ack once we have a better way to stop this thing from\n"
2217 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2218 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2219 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2220 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2221 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2222 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2225 "#else // !MODE_REFRACTION\n"
2230 "#ifdef MODE_WATER\n"
2231 "#ifdef VERTEX_SHADER\n"
2235 "float4 gl_Vertex : POSITION,\n"
2236 "uniform float4x4 ModelViewProjectionMatrix,\n"
2237 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2238 "uniform float4x4 TexMatrix,\n"
2239 "uniform float3 EyePosition,\n"
2240 "out float4 gl_Position : POSITION,\n"
2241 "out float2 TexCoord : TEXCOORD0,\n"
2242 "out float3 EyeVector : TEXCOORD1,\n"
2243 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2246 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2247 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2248 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2249 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2250 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2251 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2252 " ModelViewProjectionPosition = gl_Position;\n"
2256 "#ifdef FRAGMENT_SHADER\n"
2259 "float2 TexCoord : TEXCOORD0,\n"
2260 "float3 EyeVector : TEXCOORD1,\n"
2261 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2262 "uniform sampler2D Texture_Normal,\n"
2263 "uniform sampler2D Texture_Refraction,\n"
2264 "uniform sampler2D Texture_Reflection,\n"
2265 "uniform float4 DistortScaleRefractReflect,\n"
2266 "uniform float4 ScreenScaleRefractReflect,\n"
2267 "uniform float4 ScreenCenterRefractReflect,\n"
2268 "uniform float4 RefractColor,\n"
2269 "uniform float4 ReflectColor,\n"
2270 "uniform float ReflectFactor,\n"
2271 "uniform float ReflectOffset,\n"
2272 "out float4 gl_FragColor : COLOR\n"
2275 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2276 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2277 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2278 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2279 " // FIXME temporary hack to detect the case that the reflection\n"
2280 " // gets blackened at edges due to leaving the area that contains actual\n"
2282 " // Remove this 'ack once we have a better way to stop this thing from\n"
2284 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2285 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2286 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2287 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2288 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2289 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2290 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2291 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2292 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2293 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2294 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2295 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2298 "#else // !MODE_WATER\n"
2303 "// 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"
2305 "// fragment shader specific:\n"
2306 "#ifdef FRAGMENT_SHADER\n"
2309 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask, sampler2D Texture_FogHeightTexture)\n"
2312 "#ifdef USEFOGHEIGHTTEXTURE\n"
2313 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2314 " fogfrac = fogheightpixel.a;\n"
2315 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2317 "# ifdef USEFOGOUTSIDE\n"
2318 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2320 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2322 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2327 "#ifdef USEOFFSETMAPPING\n"
2328 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2330 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2331 " // 14 sample relief mapping: linear search and then binary search\n"
2332 " // this basically steps forward a small amount repeatedly until it finds\n"
2333 " // itself inside solid, then jitters forward and back using decreasing\n"
2334 " // amounts to find the impact\n"
2335 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2336 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2337 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2338 " float3 RT = float3(TexCoord, 1);\n"
2339 " OffsetVector *= 0.1;\n"
2340 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2341 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2342 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2343 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2344 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2345 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2346 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2347 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2348 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2349 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2350 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2351 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2352 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2353 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2356 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2357 " // this basically moves forward the full distance, and then backs up based\n"
2358 " // on height of samples\n"
2359 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2360 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2361 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2362 " TexCoord += OffsetVector;\n"
2363 " OffsetVector *= 0.333;\n"
2364 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2365 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2366 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2367 " return TexCoord;\n"
2370 "#endif // USEOFFSETMAPPING\n"
2372 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2373 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2374 "# ifdef USESHADOWMAPORTHO\n"
2375 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2377 "# ifdef USESHADOWMAPVSDCT\n"
2378 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2380 " float3 adir = abs(dir);\n"
2381 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2382 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2383 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2386 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2388 " float3 adir = abs(dir);\n"
2389 " float ma = adir.z;\n"
2390 " float4 proj = float4(dir, 2.5);\n"
2391 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2392 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2393 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2394 " 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"
2398 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2400 "#ifdef USESHADOWMAPCUBE\n"
2401 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2403 " float3 adir = abs(dir);\n"
2404 " return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2408 "# ifdef USESHADOWMAPRECT\n"
2409 "#ifdef USESHADOWMAPVSDCT\n"
2410 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2412 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2415 "#ifdef USESHADOWMAPVSDCT\n"
2416 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2418 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2421 "# ifdef USESHADOWSAMPLER\n"
2423 "# ifdef USESHADOWMAPPCF\n"
2424 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2425 " 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"
2427 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2432 "# ifdef USESHADOWMAPPCF\n"
2433 "# if USESHADOWMAPPCF > 1\n"
2434 "# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2435 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2436 " 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"
2437 " 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"
2438 " 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"
2439 " 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"
2440 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2441 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2443 "# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2444 " float2 offset = frac(shadowmaptc.xy);\n"
2445 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2446 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2447 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2448 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2449 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2452 " f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2456 "# ifdef USESHADOWMAPORTHO\n"
2457 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2464 "# ifdef USESHADOWMAP2D\n"
2465 "#ifdef USESHADOWMAPVSDCT\n"
2466 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2468 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2471 "#ifdef USESHADOWMAPVSDCT\n"
2472 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2474 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2478 "# ifdef USESHADOWSAMPLER\n"
2479 "# ifdef USESHADOWMAPPCF\n"
2480 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
2481 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2482 " 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"
2484 " f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2487 "# ifdef USESHADOWMAPPCF\n"
2488 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2489 "# ifdef GL_ARB_texture_gather\n"
2490 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2492 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2494 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2495 " center *= ShadowMap_TextureScale;\n"
2496 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2497 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2498 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2499 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2500 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2501 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2502 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2504 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale) \n"
2505 "# if USESHADOWMAPPCF > 1\n"
2506 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2507 " center *= ShadowMap_TextureScale;\n"
2508 " 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"
2509 " 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"
2510 " 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"
2511 " 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"
2512 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2513 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2515 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2516 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2517 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2518 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2519 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2520 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2524 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2527 "# ifdef USESHADOWMAPORTHO\n"
2528 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2535 "# ifdef USESHADOWMAPCUBE\n"
2536 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2538 " // apply depth texture cubemap as light filter\n"
2539 " float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2541 "# ifdef USESHADOWSAMPLER\n"
2542 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2544 " f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2549 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2550 "#endif // FRAGMENT_SHADER\n"
2555 "#ifdef MODE_DEFERREDGEOMETRY\n"
2556 "#ifdef VERTEX_SHADER\n"
2559 "float4 gl_Vertex : POSITION,\n"
2560 "uniform float4x4 ModelViewProjectionMatrix,\n"
2561 "#ifdef USEVERTEXTEXTUREBLEND\n"
2562 "float4 gl_Color : COLOR0,\n"
2564 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2565 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2566 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2567 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2568 "uniform float4x4 TexMatrix,\n"
2569 "#ifdef USEVERTEXTEXTUREBLEND\n"
2570 "uniform float4x4 BackgroundTexMatrix,\n"
2572 "uniform float4x4 ModelViewMatrix,\n"
2573 "#ifdef USEOFFSETMAPPING\n"
2574 "uniform float3 EyePosition,\n"
2576 "out float4 gl_Position : POSITION,\n"
2577 "out float4 gl_FrontColor : COLOR,\n"
2578 "out float4 TexCoordBoth : TEXCOORD0,\n"
2579 "#ifdef USEOFFSETMAPPING\n"
2580 "out float3 EyeVector : TEXCOORD2,\n"
2582 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2583 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2584 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2587 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2588 "#ifdef USEVERTEXTEXTUREBLEND\n"
2589 " gl_FrontColor = gl_Color;\n"
2590 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2593 " // transform unnormalized eye direction into tangent space\n"
2594 "#ifdef USEOFFSETMAPPING\n"
2595 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2596 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2597 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2598 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2601 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2602 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2603 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2604 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2606 "#endif // VERTEX_SHADER\n"
2608 "#ifdef FRAGMENT_SHADER\n"
2611 "float4 TexCoordBoth : TEXCOORD0,\n"
2612 "float3 EyeVector : TEXCOORD2,\n"
2613 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2614 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2615 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2616 "uniform sampler2D Texture_Normal,\n"
2617 "#ifdef USEALPHAKILL\n"
2618 "uniform sampler2D Texture_Color,\n"
2620 "uniform sampler2D Texture_Gloss,\n"
2621 "#ifdef USEVERTEXTEXTUREBLEND\n"
2622 "uniform sampler2D Texture_SecondaryNormal,\n"
2623 "uniform sampler2D Texture_SecondaryGloss,\n"
2625 "#ifdef USEOFFSETMAPPING\n"
2626 "uniform float OffsetMapping_Scale,\n"
2628 "uniform half SpecularPower,\n"
2629 "out float4 gl_FragColor : COLOR\n"
2632 " float2 TexCoord = TexCoordBoth.xy;\n"
2633 "#ifdef USEOFFSETMAPPING\n"
2634 " // apply offsetmapping\n"
2635 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2636 "#define TexCoord TexCoordOffset\n"
2639 "#ifdef USEALPHAKILL\n"
2640 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2644 "#ifdef USEVERTEXTEXTUREBLEND\n"
2645 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2646 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2647 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2648 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2651 "#ifdef USEVERTEXTEXTUREBLEND\n"
2652 " float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2653 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2655 " float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2656 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2659 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2661 "#endif // FRAGMENT_SHADER\n"
2662 "#else // !MODE_DEFERREDGEOMETRY\n"
2667 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2668 "#ifdef VERTEX_SHADER\n"
2671 "float4 gl_Vertex : POSITION,\n"
2672 "uniform float4x4 ModelViewProjectionMatrix,\n"
2673 "uniform float4x4 ModelViewMatrix,\n"
2674 "out float4 gl_Position : POSITION,\n"
2675 "out float4 ModelViewPosition : TEXCOORD0\n"
2678 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2679 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2681 "#endif // VERTEX_SHADER\n"
2683 "#ifdef FRAGMENT_SHADER\n"
2686 "float2 Pixel : WPOS,\n"
2687 "float4 ModelViewPosition : TEXCOORD0,\n"
2688 "uniform float4x4 ViewToLight,\n"
2689 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2690 "uniform float3 LightPosition,\n"
2691 "uniform half2 PixelToScreenTexCoord,\n"
2692 "uniform half3 DeferredColor_Ambient,\n"
2693 "uniform half3 DeferredColor_Diffuse,\n"
2694 "#ifdef USESPECULAR\n"
2695 "uniform half3 DeferredColor_Specular,\n"
2696 "uniform half SpecularPower,\n"
2698 "uniform sampler2D Texture_Attenuation,\n"
2699 "uniform sampler2D Texture_ScreenDepth,\n"
2700 "uniform sampler2D Texture_ScreenNormalMap,\n"
2702 "#ifdef USECUBEFILTER\n"
2703 "uniform samplerCUBE Texture_Cube,\n"
2706 "#ifdef USESHADOWMAPRECT\n"
2707 "# ifdef USESHADOWSAMPLER\n"
2708 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2710 "uniform samplerRECT Texture_ShadowMapRect,\n"
2714 "#ifdef USESHADOWMAP2D\n"
2715 "# ifdef USESHADOWSAMPLER\n"
2716 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2718 "uniform sampler2D Texture_ShadowMap2D,\n"
2722 "#ifdef USESHADOWMAPVSDCT\n"
2723 "uniform samplerCUBE Texture_CubeProjection,\n"
2726 "#ifdef USESHADOWMAPCUBE\n"
2727 "# ifdef USESHADOWSAMPLER\n"
2728 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2730 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2734 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2735 "uniform float2 ShadowMap_TextureScale,\n"
2736 "uniform float4 ShadowMap_Parameters,\n"
2739 "out float4 gl_FragData0 : COLOR0,\n"
2740 "out float4 gl_FragData1 : COLOR1\n"
2743 " // calculate viewspace pixel position\n"
2744 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2745 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2746 " float3 position;\n"
2747 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2748 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2749 " // decode viewspace pixel normal\n"
2750 " half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2751 " half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2752 " // surfacenormal = pixel normal in viewspace\n"
2753 " // LightVector = pixel to light in viewspace\n"
2754 " // CubeVector = position in lightspace\n"
2755 " // eyevector = pixel to view in viewspace\n"
2756 " float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2757 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2758 "#ifdef USEDIFFUSE\n"
2759 " // calculate diffuse shading\n"
2760 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2761 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2763 "#ifdef USESPECULAR\n"
2764 " // calculate directional shading\n"
2765 " float3 eyevector = position * -1.0;\n"
2766 "# ifdef USEEXACTSPECULARMATH\n"
2767 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2769 " half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2770 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2774 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2775 " fade *= ShadowMapCompare(CubeVector,\n"
2776 "# if defined(USESHADOWMAP2D)\n"
2777 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2779 "# if defined(USESHADOWMAPRECT)\n"
2780 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2782 "# if defined(USESHADOWMAPCUBE)\n"
2783 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2786 "#ifdef USESHADOWMAPVSDCT\n"
2787 ", Texture_CubeProjection\n"
2792 "#ifdef USEDIFFUSE\n"
2793 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2795 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2797 "#ifdef USESPECULAR\n"
2798 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2800 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2803 "# ifdef USECUBEFILTER\n"
2804 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2805 " gl_FragData0.rgb *= cubecolor;\n"
2806 " gl_FragData1.rgb *= cubecolor;\n"
2809 "#endif // FRAGMENT_SHADER\n"
2810 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2815 "#ifdef VERTEX_SHADER\n"
2818 "float4 gl_Vertex : POSITION,\n"
2819 "uniform float4x4 ModelViewProjectionMatrix,\n"
2820 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2821 "float4 gl_Color : COLOR0,\n"
2823 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2824 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2825 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2826 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2827 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2829 "uniform float3 EyePosition,\n"
2830 "uniform float4x4 TexMatrix,\n"
2831 "#ifdef USEVERTEXTEXTUREBLEND\n"
2832 "uniform float4x4 BackgroundTexMatrix,\n"
2834 "#ifdef MODE_LIGHTSOURCE\n"
2835 "uniform float4x4 ModelToLight,\n"
2837 "#ifdef MODE_LIGHTSOURCE\n"
2838 "uniform float3 LightPosition,\n"
2840 "#ifdef MODE_LIGHTDIRECTION\n"
2841 "uniform float3 LightDir,\n"
2843 "uniform float4 FogPlane,\n"
2844 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2845 "uniform float3 LightPosition,\n"
2847 "#ifdef USESHADOWMAPORTHO\n"
2848 "uniform float4x4 ShadowMapMatrix,\n"
2851 "out float4 gl_FrontColor : COLOR,\n"
2852 "out float4 TexCoordBoth : TEXCOORD0,\n"
2853 "#ifdef USELIGHTMAP\n"
2854 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2856 "#ifdef USEEYEVECTOR\n"
2857 "out float3 EyeVector : TEXCOORD2,\n"
2859 "#ifdef USEREFLECTION\n"
2860 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2863 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2865 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2866 "out float3 LightVector : TEXCOORD1,\n"
2868 "#ifdef MODE_LIGHTSOURCE\n"
2869 "out float3 CubeVector : TEXCOORD3,\n"
2871 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2872 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2873 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2874 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2876 "#ifdef USESHADOWMAPORTHO\n"
2877 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2879 "out float4 gl_Position : POSITION\n"
2882 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2883 " gl_FrontColor = gl_Color;\n"
2885 " // copy the surface texcoord\n"
2886 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2887 "#ifdef USEVERTEXTEXTUREBLEND\n"
2888 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2890 "#ifdef USELIGHTMAP\n"
2891 " TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2894 "#ifdef MODE_LIGHTSOURCE\n"
2895 " // transform vertex position into light attenuation/cubemap space\n"
2896 " // (-1 to +1 across the light box)\n"
2897 " CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2899 "# ifdef USEDIFFUSE\n"
2900 " // transform unnormalized light direction into tangent space\n"
2901 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2902 " // normalize it per pixel)\n"
2903 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2904 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2905 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2906 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2910 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2911 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2912 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2913 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2916 " // transform unnormalized eye direction into tangent space\n"
2917 "#ifdef USEEYEVECTOR\n"
2918 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2919 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2920 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2921 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2925 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2926 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2929 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2930 " VectorS = gl_MultiTexCoord1.xyz;\n"
2931 " VectorT = gl_MultiTexCoord2.xyz;\n"
2932 " VectorR = gl_MultiTexCoord3.xyz;\n"
2935 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2936 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2938 "#ifdef USESHADOWMAPORTHO\n"
2939 " ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2942 "#ifdef USEREFLECTION\n"
2943 " ModelViewProjectionPosition = gl_Position;\n"
2946 "#endif // VERTEX_SHADER\n"
2951 "#ifdef FRAGMENT_SHADER\n"
2954 "#ifdef USEDEFERREDLIGHTMAP\n"
2955 "float2 Pixel : WPOS,\n"
2957 "float4 gl_FrontColor : COLOR,\n"
2958 "float4 TexCoordBoth : TEXCOORD0,\n"
2959 "#ifdef USELIGHTMAP\n"
2960 "float2 TexCoordLightmap : TEXCOORD1,\n"
2962 "#ifdef USEEYEVECTOR\n"
2963 "float3 EyeVector : TEXCOORD2,\n"
2965 "#ifdef USEREFLECTION\n"
2966 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2969 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2971 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2972 "float3 LightVector : TEXCOORD1,\n"
2974 "#ifdef MODE_LIGHTSOURCE\n"
2975 "float3 CubeVector : TEXCOORD3,\n"
2977 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2978 "float4 ModelViewPosition : TEXCOORD0,\n"
2980 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2981 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2982 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2983 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2985 "#ifdef USESHADOWMAPORTHO\n"
2986 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2989 "uniform sampler2D Texture_Normal,\n"
2990 "uniform sampler2D Texture_Color,\n"
2991 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2992 "uniform sampler2D Texture_Gloss,\n"
2995 "uniform sampler2D Texture_Glow,\n"
2997 "#ifdef USEVERTEXTEXTUREBLEND\n"
2998 "uniform sampler2D Texture_SecondaryNormal,\n"
2999 "uniform sampler2D Texture_SecondaryColor,\n"
3000 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3001 "uniform sampler2D Texture_SecondaryGloss,\n"
3004 "uniform sampler2D Texture_SecondaryGlow,\n"
3007 "#ifdef USECOLORMAPPING\n"
3008 "uniform sampler2D Texture_Pants,\n"
3009 "uniform sampler2D Texture_Shirt,\n"
3012 "uniform sampler2D Texture_FogHeightTexture,\n"
3013 "uniform sampler2D Texture_FogMask,\n"
3015 "#ifdef USELIGHTMAP\n"
3016 "uniform sampler2D Texture_Lightmap,\n"
3018 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3019 "uniform sampler2D Texture_Deluxemap,\n"
3021 "#ifdef USEREFLECTION\n"
3022 "uniform sampler2D Texture_Reflection,\n"
3025 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3026 "uniform sampler2D Texture_ScreenDepth,\n"
3027 "uniform sampler2D Texture_ScreenNormalMap,\n"
3029 "#ifdef USEDEFERREDLIGHTMAP\n"
3030 "uniform sampler2D Texture_ScreenDiffuse,\n"
3031 "uniform sampler2D Texture_ScreenSpecular,\n"
3034 "#ifdef USECOLORMAPPING\n"
3035 "uniform half3 Color_Pants,\n"
3036 "uniform half3 Color_Shirt,\n"
3039 "uniform float3 FogColor,\n"
3040 "uniform float FogRangeRecip,\n"
3041 "uniform float FogPlaneViewDist,\n"
3042 "uniform float FogHeightFade,\n"
3045 "#ifdef USEOFFSETMAPPING\n"
3046 "uniform float OffsetMapping_Scale,\n"
3049 "#ifdef USEDEFERREDLIGHTMAP\n"
3050 "uniform half2 PixelToScreenTexCoord,\n"
3051 "uniform half3 DeferredMod_Diffuse,\n"
3052 "uniform half3 DeferredMod_Specular,\n"
3054 "uniform half3 Color_Ambient,\n"
3055 "uniform half3 Color_Diffuse,\n"
3056 "uniform half3 Color_Specular,\n"
3057 "uniform half SpecularPower,\n"
3059 "uniform half3 Color_Glow,\n"
3061 "uniform half Alpha,\n"
3062 "#ifdef USEREFLECTION\n"
3063 "uniform float4 DistortScaleRefractReflect,\n"
3064 "uniform float4 ScreenScaleRefractReflect,\n"
3065 "uniform float4 ScreenCenterRefractReflect,\n"
3066 "uniform half4 ReflectColor,\n"
3068 "#ifdef USEREFLECTCUBE\n"
3069 "uniform float4x4 ModelToReflectCube,\n"
3070 "uniform sampler2D Texture_ReflectMask,\n"
3071 "uniform samplerCUBE Texture_ReflectCube,\n"
3073 "#ifdef MODE_LIGHTDIRECTION\n"
3074 "uniform half3 LightColor,\n"
3076 "#ifdef MODE_LIGHTSOURCE\n"
3077 "uniform half3 LightColor,\n"
3080 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3081 "uniform sampler2D Texture_Attenuation,\n"
3082 "uniform samplerCUBE Texture_Cube,\n"
3085 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3087 "#ifdef USESHADOWMAPRECT\n"
3088 "# ifdef USESHADOWSAMPLER\n"
3089 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
3091 "uniform samplerRECT Texture_ShadowMapRect,\n"
3095 "#ifdef USESHADOWMAP2D\n"
3096 "# ifdef USESHADOWSAMPLER\n"
3097 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
3099 "uniform sampler2D Texture_ShadowMap2D,\n"
3103 "#ifdef USESHADOWMAPVSDCT\n"
3104 "uniform samplerCUBE Texture_CubeProjection,\n"
3107 "#ifdef USESHADOWMAPCUBE\n"
3108 "# ifdef USESHADOWSAMPLER\n"
3109 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
3111 "uniform samplerCUBE Texture_ShadowMapCube,\n"
3115 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3116 "uniform float2 ShadowMap_TextureScale,\n"
3117 "uniform float4 ShadowMap_Parameters,\n"
3119 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3121 "out float4 gl_FragColor : COLOR\n"
3124 " float2 TexCoord = TexCoordBoth.xy;\n"
3125 "#ifdef USEVERTEXTEXTUREBLEND\n"
3126 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3128 "#ifdef USEOFFSETMAPPING\n"
3129 " // apply offsetmapping\n"
3130 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3131 "#define TexCoord TexCoordOffset\n"
3134 " // combine the diffuse textures (base, pants, shirt)\n"
3135 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3136 "#ifdef USEALPHAKILL\n"
3137 " if (color.a < 0.5)\n"
3140 " color.a *= Alpha;\n"
3141 "#ifdef USECOLORMAPPING\n"
3142 " color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
3144 "#ifdef USEVERTEXTEXTUREBLEND\n"
3145 " float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3146 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3147 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3148 " color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
3150 " //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
3153 " // get the surface normal\n"
3154 "#ifdef USEVERTEXTEXTUREBLEND\n"
3155 " half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3157 " half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
3160 " // get the material colors\n"
3161 " half3 diffusetex = color.rgb;\n"
3162 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3163 "# ifdef USEVERTEXTEXTUREBLEND\n"
3164 " half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
3166 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3170 "#ifdef USEREFLECTCUBE\n"
3171 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3172 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3173 " float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3174 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3180 "#ifdef MODE_LIGHTSOURCE\n"
3181 " // light source\n"
3182 "#ifdef USEDIFFUSE\n"
3183 " half3 lightnormal = half3(normalize(LightVector));\n"
3184 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3185 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3186 "#ifdef USESPECULAR\n"
3187 "#ifdef USEEXACTSPECULARMATH\n"
3188 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3190 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3191 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3193 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3196 " color.rgb = diffusetex * Color_Ambient;\n"
3198 " color.rgb *= LightColor;\n"
3199 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3200 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3201 " color.rgb *= ShadowMapCompare(CubeVector,\n"
3202 "# if defined(USESHADOWMAP2D)\n"
3203 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3205 "# if defined(USESHADOWMAPRECT)\n"
3206 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3208 "# if defined(USESHADOWMAPCUBE)\n"
3209 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3212 "#ifdef USESHADOWMAPVSDCT\n"
3213 ", Texture_CubeProjection\n"
3218 "# ifdef USECUBEFILTER\n"
3219 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3221 "#endif // MODE_LIGHTSOURCE\n"
3226 "#ifdef MODE_LIGHTDIRECTION\n"
3228 "#ifdef USEDIFFUSE\n"
3229 " half3 lightnormal = half3(normalize(LightVector));\n"
3231 "#define lightcolor LightColor\n"
3232 "#endif // MODE_LIGHTDIRECTION\n"
3233 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3235 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3236 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3237 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3238 " // convert modelspace light vector to tangentspace\n"
3239 " half3 lightnormal;\n"
3240 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3241 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3242 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3243 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3244 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3245 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3246 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3247 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3248 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3249 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3250 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3251 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3252 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3253 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3254 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3256 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3257 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3258 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3264 "#ifdef MODE_FAKELIGHT\n"
3266 "half3 lightnormal = half3(normalize(EyeVector));\n"
3267 "half3 lightcolor = half3(1.0);\n"
3268 "#endif // MODE_FAKELIGHT\n"
3273 "#ifdef MODE_LIGHTMAP\n"
3274 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3275 "#endif // MODE_LIGHTMAP\n"
3276 "#ifdef MODE_VERTEXCOLOR\n"
3277 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3278 "#endif // MODE_VERTEXCOLOR\n"
3279 "#ifdef MODE_FLATCOLOR\n"
3280 " color.rgb = diffusetex * Color_Ambient;\n"
3281 "#endif // MODE_FLATCOLOR\n"
3287 "# ifdef USEDIFFUSE\n"
3288 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3289 "# ifdef USESPECULAR\n"
3290 "# ifdef USEEXACTSPECULARMATH\n"
3291 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3293 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3294 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3296 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3298 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3301 " color.rgb = diffusetex * Color_Ambient;\n"
3305 "#ifdef USESHADOWMAPORTHO\n"
3306 " color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3307 "# if defined(USESHADOWMAP2D)\n"
3308 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3310 "# if defined(USESHADOWMAPRECT)\n"
3311 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3316 "#ifdef USEDEFERREDLIGHTMAP\n"
3317 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3318 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3319 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3323 "#ifdef USEVERTEXTEXTUREBLEND\n"
3324 " color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3326 " color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3331 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3334 " // 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"
3335 "#ifdef USEREFLECTION\n"
3336 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3337 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3338 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3339 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3340 " // FIXME temporary hack to detect the case that the reflection\n"
3341 " // gets blackened at edges due to leaving the area that contains actual\n"
3343 " // Remove this 'ack once we have a better way to stop this thing from\n"
3345 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3346 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3347 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3348 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3349 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3350 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3353 " gl_FragColor = float4(color);\n"
3355 "#endif // FRAGMENT_SHADER\n"
3357 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3358 "#endif // !MODE_DEFERREDGEOMETRY\n"
3359 "#endif // !MODE_WATER\n"
3360 "#endif // !MODE_REFRACTION\n"
3361 "#endif // !MODE_BLOOMBLUR\n"
3362 "#endif // !MODE_GENERIC\n"
3363 "#endif // !MODE_POSTPROCESS\n"
3364 "#endif // !MODE_SHOWDEPTH\n"
3365 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3368 char *glslshaderstring = NULL;
3369 char *cgshaderstring = NULL;
3371 //=======================================================================================================================================================
3373 typedef struct shaderpermutationinfo_s
3375 const char *pretext;
3378 shaderpermutationinfo_t;
3380 typedef struct shadermodeinfo_s
3382 const char *vertexfilename;
3383 const char *geometryfilename;
3384 const char *fragmentfilename;
3385 const char *pretext;
3390 typedef enum shaderpermutation_e
3392 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3393 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3394 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3395 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3396 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3397 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3398 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3399 SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3400 SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3401 SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3402 SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3403 SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3404 SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3405 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3406 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3407 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3408 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3409 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3410 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3411 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3412 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3413 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3414 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3415 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3416 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
3417 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3418 SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3419 SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
3420 SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<28, // (water) counter-direction normalmaps scrolling
3421 SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3422 SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3424 shaderpermutation_t;
3426 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3427 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3429 {"#define USEDIFFUSE\n", " diffuse"},
3430 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3431 {"#define USEVIEWTINT\n", " viewtint"},
3432 {"#define USECOLORMAPPING\n", " colormapping"},
3433 {"#define USESATURATION\n", " saturation"},
3434 {"#define USEFOGINSIDE\n", " foginside"},
3435 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3436 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3437 {"#define USEGAMMARAMPS\n", " gammaramps"},
3438 {"#define USECUBEFILTER\n", " cubefilter"},
3439 {"#define USEGLOW\n", " glow"},
3440 {"#define USEBLOOM\n", " bloom"},
3441 {"#define USESPECULAR\n", " specular"},
3442 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3443 {"#define USEREFLECTION\n", " reflection"},
3444 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3445 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3446 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3447 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3448 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3449 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3450 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3451 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3452 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3453 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3454 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3455 {"#define USEALPHAKILL\n", " alphakill"},
3456 {"#define USEREFLECTCUBE\n", " reflectcube"},
3457 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3460 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3461 typedef enum shadermode_e
3463 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3464 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3465 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3466 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3467 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3468 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3469 SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3470 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3471 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3472 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3473 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3474 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3475 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3476 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3477 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3478 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3483 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3484 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3486 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3487 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3488 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3489 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3490 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3491 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3492 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3493 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3494 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3495 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3496 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3497 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3498 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3499 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3500 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3501 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3505 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3507 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3508 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3509 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3510 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3511 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3512 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3513 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3514 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3515 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3516 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3517 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3518 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3519 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3520 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3521 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3522 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3526 struct r_glsl_permutation_s;
3527 typedef struct r_glsl_permutation_s
3529 /// hash lookup data
3530 struct r_glsl_permutation_s *hashnext;
3532 unsigned int permutation;
3534 /// indicates if we have tried compiling this permutation already
3536 /// 0 if compilation failed
3538 /// locations of detected uniforms in program object, or -1 if not found
3539 int loc_Texture_First;
3540 int loc_Texture_Second;
3541 int loc_Texture_GammaRamps;
3542 int loc_Texture_Normal;
3543 int loc_Texture_Color;
3544 int loc_Texture_Gloss;
3545 int loc_Texture_Glow;
3546 int loc_Texture_SecondaryNormal;
3547 int loc_Texture_SecondaryColor;
3548 int loc_Texture_SecondaryGloss;
3549 int loc_Texture_SecondaryGlow;
3550 int loc_Texture_Pants;
3551 int loc_Texture_Shirt;
3552 int loc_Texture_FogHeightTexture;
3553 int loc_Texture_FogMask;
3554 int loc_Texture_Lightmap;
3555 int loc_Texture_Deluxemap;
3556 int loc_Texture_Attenuation;
3557 int loc_Texture_Cube;
3558 int loc_Texture_Refraction;
3559 int loc_Texture_Reflection;
3560 int loc_Texture_ShadowMapRect;
3561 int loc_Texture_ShadowMapCube;
3562 int loc_Texture_ShadowMap2D;
3563 int loc_Texture_CubeProjection;
3564 int loc_Texture_ScreenDepth;
3565 int loc_Texture_ScreenNormalMap;
3566 int loc_Texture_ScreenDiffuse;
3567 int loc_Texture_ScreenSpecular;
3568 int loc_Texture_ReflectMask;
3569 int loc_Texture_ReflectCube;
3571 int loc_BloomBlur_Parameters;
3573 int loc_Color_Ambient;
3574 int loc_Color_Diffuse;
3575 int loc_Color_Specular;
3577 int loc_Color_Pants;
3578 int loc_Color_Shirt;
3579 int loc_DeferredColor_Ambient;
3580 int loc_DeferredColor_Diffuse;
3581 int loc_DeferredColor_Specular;
3582 int loc_DeferredMod_Diffuse;
3583 int loc_DeferredMod_Specular;
3584 int loc_DistortScaleRefractReflect;
3585 int loc_EyePosition;
3587 int loc_FogHeightFade;
3589 int loc_FogPlaneViewDist;
3590 int loc_FogRangeRecip;
3593 int loc_LightPosition;
3594 int loc_OffsetMapping_Scale;
3596 int loc_ReflectColor;
3597 int loc_ReflectFactor;
3598 int loc_ReflectOffset;
3599 int loc_RefractColor;
3601 int loc_ScreenCenterRefractReflect;
3602 int loc_ScreenScaleRefractReflect;
3603 int loc_ScreenToDepth;
3604 int loc_ShadowMap_Parameters;
3605 int loc_ShadowMap_TextureScale;
3606 int loc_SpecularPower;
3611 int loc_ViewTintColor;
3612 int loc_ViewToLight;
3613 int loc_ModelToLight;
3615 int loc_BackgroundTexMatrix;
3616 int loc_ModelViewProjectionMatrix;
3617 int loc_ModelViewMatrix;
3618 int loc_PixelToScreenTexCoord;
3619 int loc_ModelToReflectCube;
3620 int loc_ShadowMapMatrix;
3621 int loc_NormalmapScrollBlend;
3623 r_glsl_permutation_t;
3625 #define SHADERPERMUTATION_HASHSIZE 256
3628 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3629 // these can NOT degrade! only use for simple stuff
3632 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3633 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3635 #define SHADERSTATICPARMS_COUNT 2
3637 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3638 static int shaderstaticparms_count = 0;
3640 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3641 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3642 qboolean R_CompileShader_CheckStaticParms(void)
3644 static int r_compileshader_staticparms_save[1];
3645 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3646 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3649 if (r_glsl_saturation_redcompensate.integer)
3650 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3651 if(r_shadow_glossexact.integer)
3652 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3654 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms));
3657 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3658 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3659 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3661 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3662 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3664 shaderstaticparms_count = 0;
3667 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3668 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3672 /// information about each possible shader permutation
3673 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3674 /// currently selected permutation
3675 r_glsl_permutation_t *r_glsl_permutation;
3676 /// storage for permutations linked in the hash table
3677 memexpandablearray_t r_glsl_permutationarray;
3679 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3681 //unsigned int hashdepth = 0;
3682 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3683 r_glsl_permutation_t *p;
3684 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3686 if (p->mode == mode && p->permutation == permutation)
3688 //if (hashdepth > 10)
3689 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3694 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3696 p->permutation = permutation;
3697 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3698 r_glsl_permutationhash[mode][hashindex] = p;
3699 //if (hashdepth > 10)
3700 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3704 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3707 if (!filename || !filename[0])
3709 if (!strcmp(filename, "glsl/default.glsl"))
3711 if (!glslshaderstring)
3713 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3714 if (glslshaderstring)
3715 Con_DPrintf("Loading shaders from file %s...\n", filename);
3717 glslshaderstring = (char *)builtinshaderstring;
3719 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3720 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3721 return shaderstring;
3723 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3726 if (printfromdisknotice)
3727 Con_DPrintf("from disk %s... ", filename);
3728 return shaderstring;
3730 return shaderstring;
3733 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3736 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3737 char *vertexstring, *geometrystring, *fragmentstring;
3738 char permutationname[256];
3739 int vertstrings_count = 0;
3740 int geomstrings_count = 0;
3741 int fragstrings_count = 0;
3742 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3743 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3744 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3751 permutationname[0] = 0;
3752 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3753 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3754 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3756 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3758 // the first pretext is which type of shader to compile as
3759 // (later these will all be bound together as a program object)
3760 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3761 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3762 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3764 // the second pretext is the mode (for example a light source)
3765 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3766 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3767 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3768 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3770 // now add all the permutation pretexts
3771 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3773 if (permutation & (1<<i))
3775 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3776 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3777 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3778 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3782 // keep line numbers correct
3783 vertstrings_list[vertstrings_count++] = "\n";
3784 geomstrings_list[geomstrings_count++] = "\n";
3785 fragstrings_list[fragstrings_count++] = "\n";
3790 R_CompileShader_AddStaticParms(mode, permutation);
3791 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3792 vertstrings_count += shaderstaticparms_count;
3793 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3794 geomstrings_count += shaderstaticparms_count;
3795 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3796 fragstrings_count += shaderstaticparms_count;
3798 // now append the shader text itself
3799 vertstrings_list[vertstrings_count++] = vertexstring;
3800 geomstrings_list[geomstrings_count++] = geometrystring;
3801 fragstrings_list[fragstrings_count++] = fragmentstring;
3803 // if any sources were NULL, clear the respective list
3805 vertstrings_count = 0;
3806 if (!geometrystring)
3807 geomstrings_count = 0;
3808 if (!fragmentstring)
3809 fragstrings_count = 0;
3811 // compile the shader program
3812 if (vertstrings_count + geomstrings_count + fragstrings_count)
3813 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3817 qglUseProgramObjectARB(p->program);CHECKGLERROR
3818 // look up all the uniform variable names we care about, so we don't
3819 // have to look them up every time we set them
3821 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3822 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3823 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3824 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3825 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3826 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3827 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3828 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3829 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3830 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3831 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3832 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3833 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3834 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3835 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3836 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3837 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3838 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3839 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3840 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3841 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3842 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3843 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3844 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3845 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3846 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3847 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3848 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3849 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3850 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3851 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3852 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3853 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3854 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3855 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3856 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3857 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3858 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3859 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3860 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3861 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3862 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3863 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3864 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3865 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3866 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3867 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3868 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3869 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3870 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3871 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3872 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3873 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3874 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3875 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3876 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3877 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3878 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3879 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3880 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3881 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3882 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3883 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3884 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3885 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3886 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3887 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3888 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3889 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3890 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3891 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3892 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3893 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3894 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3895 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3896 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3897 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3898 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3899 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3900 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3901 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3902 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3903 p->loc_NormalmapScrollBlend = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3904 // initialize the samplers to refer to the texture units we use
3905 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3906 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3907 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3908 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3909 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3910 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3911 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3912 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3913 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3914 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3915 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3916 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3917 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3918 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3919 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3920 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3921 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3922 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3923 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3924 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3925 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3926 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3927 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
3928 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3929 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3930 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3931 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3932 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3933 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3934 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3935 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3937 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3940 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3944 Mem_Free(vertexstring);
3946 Mem_Free(geometrystring);
3948 Mem_Free(fragmentstring);
3951 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3953 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3954 if (r_glsl_permutation != perm)
3956 r_glsl_permutation = perm;
3957 if (!r_glsl_permutation->program)
3959 if (!r_glsl_permutation->compiled)
3960 R_GLSL_CompilePermutation(perm, mode, permutation);
3961 if (!r_glsl_permutation->program)
3963 // remove features until we find a valid permutation
3965 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3967 // reduce i more quickly whenever it would not remove any bits
3968 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3969 if (!(permutation & j))
3972 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3973 if (!r_glsl_permutation->compiled)
3974 R_GLSL_CompilePermutation(perm, mode, permutation);
3975 if (r_glsl_permutation->program)
3978 if (i >= SHADERPERMUTATION_COUNT)
3980 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3981 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3982 qglUseProgramObjectARB(0);CHECKGLERROR
3983 return; // no bit left to clear, entire mode is broken
3988 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3990 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3991 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3992 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3996 #include <Cg/cgGL.h>
3997 struct r_cg_permutation_s;
3998 typedef struct r_cg_permutation_s
4000 /// hash lookup data
4001 struct r_cg_permutation_s *hashnext;
4003 unsigned int permutation;
4005 /// indicates if we have tried compiling this permutation already
4007 /// 0 if compilation failed
4010 /// locations of detected parameters in programs, or NULL if not found
4011 CGparameter vp_EyePosition;
4012 CGparameter vp_FogPlane;
4013 CGparameter vp_LightDir;
4014 CGparameter vp_LightPosition;
4015 CGparameter vp_ModelToLight;
4016 CGparameter vp_TexMatrix;
4017 CGparameter vp_BackgroundTexMatrix;
4018 CGparameter vp_ModelViewProjectionMatrix;
4019 CGparameter vp_ModelViewMatrix;
4020 CGparameter vp_ShadowMapMatrix;
4022 CGparameter fp_Texture_First;
4023 CGparameter fp_Texture_Second;
4024 CGparameter fp_Texture_GammaRamps;
4025 CGparameter fp_Texture_Normal;
4026 CGparameter fp_Texture_Color;
4027 CGparameter fp_Texture_Gloss;
4028 CGparameter fp_Texture_Glow;
4029 CGparameter fp_Texture_SecondaryNormal;
4030 CGparameter fp_Texture_SecondaryColor;
4031 CGparameter fp_Texture_SecondaryGloss;
4032 CGparameter fp_Texture_SecondaryGlow;
4033 CGparameter fp_Texture_Pants;
4034 CGparameter fp_Texture_Shirt;
4035 CGparameter fp_Texture_FogHeightTexture;
4036 CGparameter fp_Texture_FogMask;
4037 CGparameter fp_Texture_Lightmap;
4038 CGparameter fp_Texture_Deluxemap;
4039 CGparameter fp_Texture_Attenuation;
4040 CGparameter fp_Texture_Cube;
4041 CGparameter fp_Texture_Refraction;
4042 CGparameter fp_Texture_Reflection;
4043 CGparameter fp_Texture_ShadowMapRect;
4044 CGparameter fp_Texture_ShadowMapCube;
4045 CGparameter fp_Texture_ShadowMap2D;
4046 CGparameter fp_Texture_CubeProjection;
4047 CGparameter fp_Texture_ScreenDepth;
4048 CGparameter fp_Texture_ScreenNormalMap;
4049 CGparameter fp_Texture_ScreenDiffuse;
4050 CGparameter fp_Texture_ScreenSpecular;
4051 CGparameter fp_Texture_ReflectMask;
4052 CGparameter fp_Texture_ReflectCube;
4053 CGparameter fp_Alpha;
4054 CGparameter fp_BloomBlur_Parameters;
4055 CGparameter fp_ClientTime;
4056 CGparameter fp_Color_Ambient;
4057 CGparameter fp_Color_Diffuse;
4058 CGparameter fp_Color_Specular;
4059 CGparameter fp_Color_Glow;
4060 CGparameter fp_Color_Pants;
4061 CGparameter fp_Color_Shirt;
4062 CGparameter fp_DeferredColor_Ambient;
4063 CGparameter fp_DeferredColor_Diffuse;
4064 CGparameter fp_DeferredColor_Specular;
4065 CGparameter fp_DeferredMod_Diffuse;
4066 CGparameter fp_DeferredMod_Specular;
4067 CGparameter fp_DistortScaleRefractReflect;
4068 CGparameter fp_EyePosition;
4069 CGparameter fp_FogColor;
4070 CGparameter fp_FogHeightFade;
4071 CGparameter fp_FogPlane;
4072 CGparameter fp_FogPlaneViewDist;
4073 CGparameter fp_FogRangeRecip;
4074 CGparameter fp_LightColor;
4075 CGparameter fp_LightDir;
4076 CGparameter fp_LightPosition;
4077 CGparameter fp_OffsetMapping_Scale;
4078 CGparameter fp_PixelSize;
4079 CGparameter fp_ReflectColor;
4080 CGparameter fp_ReflectFactor;
4081 CGparameter fp_ReflectOffset;
4082 CGparameter fp_RefractColor;
4083 CGparameter fp_Saturation;
4084 CGparameter fp_ScreenCenterRefractReflect;
4085 CGparameter fp_ScreenScaleRefractReflect;
4086 CGparameter fp_ScreenToDepth;
4087 CGparameter fp_ShadowMap_Parameters;
4088 CGparameter fp_ShadowMap_TextureScale;
4089 CGparameter fp_SpecularPower;
4090 CGparameter fp_UserVec1;
4091 CGparameter fp_UserVec2;
4092 CGparameter fp_UserVec3;
4093 CGparameter fp_UserVec4;
4094 CGparameter fp_ViewTintColor;
4095 CGparameter fp_ViewToLight;
4096 CGparameter fp_PixelToScreenTexCoord;
4097 CGparameter fp_ModelToReflectCube;
4098 CGparameter fp_NormalmapScrollBlend;
4102 /// information about each possible shader permutation
4103 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4104 /// currently selected permutation
4105 r_cg_permutation_t *r_cg_permutation;
4106 /// storage for permutations linked in the hash table
4107 memexpandablearray_t r_cg_permutationarray;
4109 #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));}}
4111 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4113 //unsigned int hashdepth = 0;
4114 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4115 r_cg_permutation_t *p;
4116 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4118 if (p->mode == mode && p->permutation == permutation)
4120 //if (hashdepth > 10)
4121 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4126 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4128 p->permutation = permutation;
4129 p->hashnext = r_cg_permutationhash[mode][hashindex];
4130 r_cg_permutationhash[mode][hashindex] = p;
4131 //if (hashdepth > 10)
4132 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4136 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4139 if (!filename || !filename[0])
4141 if (!strcmp(filename, "cg/default.cg"))
4143 if (!cgshaderstring)
4145 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4147 Con_DPrintf("Loading shaders from file %s...\n", filename);
4149 cgshaderstring = (char *)builtincgshaderstring;
4151 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4152 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4153 return shaderstring;
4155 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4158 if (printfromdisknotice)
4159 Con_DPrintf("from disk %s... ", filename);
4160 return shaderstring;
4162 return shaderstring;
4165 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4167 // TODO: load or create .fp and .vp shader files
4170 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4173 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4174 int vertstring_length = 0;
4175 int geomstring_length = 0;
4176 int fragstring_length = 0;
4178 char *vertexstring, *geometrystring, *fragmentstring;
4179 char *vertstring, *geomstring, *fragstring;
4180 char permutationname[256];
4181 char cachename[256];
4182 CGprofile vertexProfile;
4183 CGprofile fragmentProfile;
4184 int vertstrings_count = 0;
4185 int geomstrings_count = 0;
4186 int fragstrings_count = 0;
4187 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4188 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4189 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4197 permutationname[0] = 0;
4199 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4200 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4201 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4203 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4204 strlcat(cachename, "cg/", sizeof(cachename));
4206 // the first pretext is which type of shader to compile as
4207 // (later these will all be bound together as a program object)
4208 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4209 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4210 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4212 // the second pretext is the mode (for example a light source)
4213 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4214 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4215 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4216 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4217 strlcat(cachename, modeinfo->name, sizeof(cachename));
4219 // now add all the permutation pretexts
4220 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4222 if (permutation & (1<<i))
4224 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4225 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4226 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4227 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4228 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4232 // keep line numbers correct
4233 vertstrings_list[vertstrings_count++] = "\n";
4234 geomstrings_list[geomstrings_count++] = "\n";
4235 fragstrings_list[fragstrings_count++] = "\n";
4240 R_CompileShader_AddStaticParms(mode, permutation);
4241 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4242 vertstrings_count += shaderstaticparms_count;
4243 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4244 geomstrings_count += shaderstaticparms_count;
4245 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4246 fragstrings_count += shaderstaticparms_count;
4248 // replace spaces in the cachename with _ characters
4249 for (i = 0;cachename[i];i++)
4250 if (cachename[i] == ' ')
4253 // now append the shader text itself
4254 vertstrings_list[vertstrings_count++] = vertexstring;
4255 geomstrings_list[geomstrings_count++] = geometrystring;
4256 fragstrings_list[fragstrings_count++] = fragmentstring;
4258 // if any sources were NULL, clear the respective list
4260 vertstrings_count = 0;
4261 if (!geometrystring)
4262 geomstrings_count = 0;
4263 if (!fragmentstring)
4264 fragstrings_count = 0;
4266 vertstring_length = 0;
4267 for (i = 0;i < vertstrings_count;i++)
4268 vertstring_length += strlen(vertstrings_list[i]);
4269 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4270 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4271 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4273 geomstring_length = 0;
4274 for (i = 0;i < geomstrings_count;i++)
4275 geomstring_length += strlen(geomstrings_list[i]);
4276 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4277 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4278 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4280 fragstring_length = 0;
4281 for (i = 0;i < fragstrings_count;i++)
4282 fragstring_length += strlen(fragstrings_list[i]);
4283 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4284 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4285 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4289 //vertexProfile = CG_PROFILE_ARBVP1;
4290 //fragmentProfile = CG_PROFILE_ARBFP1;
4291 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4292 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4293 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4294 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4295 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4298 // try to load the cached shader, or generate one
4299 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4301 // if caching failed, do a dynamic compile for now
4303 if (vertstring[0] && !p->vprogram)
4304 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4306 if (fragstring[0] && !p->fprogram)
4307 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4310 // look up all the uniform variable names we care about, so we don't
4311 // have to look them up every time we set them
4315 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4316 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4317 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4318 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4319 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4320 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4321 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4322 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4323 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4324 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4325 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4326 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4332 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4333 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4334 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4335 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4336 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4337 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4338 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4339 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4340 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4341 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4342 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4343 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4344 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4345 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4346 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4347 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4348 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4349 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4350 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4351 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4352 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4353 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4354 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4355 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4356 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4357 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4358 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4359 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4360 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4361 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4362 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4363 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4364 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4365 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4366 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4367 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4368 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4369 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4370 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4371 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4372 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4373 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4374 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4375 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4376 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4377 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4378 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4379 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4380 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4381 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4382 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4383 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4384 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4385 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4386 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4387 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4388 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4389 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4390 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4391 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4392 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4393 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4394 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4395 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4396 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4397 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4398 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4399 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4400 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4401 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4402 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4403 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4404 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4405 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4406 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4407 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4408 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4409 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4410 p->fp_NormalmapScrollBlend = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4414 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4415 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4417 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4421 Mem_Free(vertstring);
4423 Mem_Free(geomstring);
4425 Mem_Free(fragstring);
4427 Mem_Free(vertexstring);
4429 Mem_Free(geometrystring);
4431 Mem_Free(fragmentstring);
4434 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4436 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4439 if (r_cg_permutation != perm)
4441 r_cg_permutation = perm;
4442 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4444 if (!r_cg_permutation->compiled)
4445 R_CG_CompilePermutation(perm, mode, permutation);
4446 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4448 // remove features until we find a valid permutation
4450 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4452 // reduce i more quickly whenever it would not remove any bits
4453 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4454 if (!(permutation & j))
4457 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4458 if (!r_cg_permutation->compiled)
4459 R_CG_CompilePermutation(perm, mode, permutation);
4460 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4463 if (i >= SHADERPERMUTATION_COUNT)
4465 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4466 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4467 return; // no bit left to clear, entire mode is broken
4473 if (r_cg_permutation->vprogram)
4475 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4476 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4477 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4481 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4482 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4484 if (r_cg_permutation->fprogram)
4486 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4487 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4488 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4492 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4493 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4497 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4498 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4499 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4502 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4504 cgGLSetTextureParameter(param, R_GetTexture(tex));
4505 cgGLEnableTextureParameter(param);
4509 void R_GLSL_Restart_f(void)
4511 unsigned int i, limit;
4512 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4513 Mem_Free(glslshaderstring);
4514 glslshaderstring = NULL;
4515 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4516 Mem_Free(cgshaderstring);
4517 cgshaderstring = NULL;
4518 switch(vid.renderpath)
4520 case RENDERPATH_GL20:
4522 r_glsl_permutation_t *p;
4523 r_glsl_permutation = NULL;
4524 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4525 for (i = 0;i < limit;i++)
4527 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4529 GL_Backend_FreeProgram(p->program);
4530 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4533 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4536 case RENDERPATH_CGGL:
4539 r_cg_permutation_t *p;
4540 r_cg_permutation = NULL;
4541 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4542 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4543 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4544 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4545 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4546 for (i = 0;i < limit;i++)
4548 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4551 cgDestroyProgram(p->vprogram);
4553 cgDestroyProgram(p->fprogram);
4554 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4557 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4561 case RENDERPATH_GL13:
4562 case RENDERPATH_GL11:
4567 void R_GLSL_DumpShader_f(void)
4572 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4575 FS_Print(file, "/* The engine may define the following macros:\n");
4576 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4577 for (i = 0;i < SHADERMODE_COUNT;i++)
4578 FS_Print(file, glslshadermodeinfo[i].pretext);
4579 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4580 FS_Print(file, shaderpermutationinfo[i].pretext);
4581 FS_Print(file, "*/\n");
4582 FS_Print(file, builtinshaderstring);
4584 Con_Printf("glsl/default.glsl written\n");
4587 Con_Printf("failed to write to glsl/default.glsl\n");
4590 file = FS_OpenRealFile("cg/default.cg", "w", false);
4593 FS_Print(file, "/* The engine may define the following macros:\n");
4594 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4595 for (i = 0;i < SHADERMODE_COUNT;i++)
4596 FS_Print(file, cgshadermodeinfo[i].pretext);
4597 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4598 FS_Print(file, shaderpermutationinfo[i].pretext);
4599 FS_Print(file, "*/\n");
4600 FS_Print(file, builtincgshaderstring);
4602 Con_Printf("cg/default.cg written\n");
4605 Con_Printf("failed to write to cg/default.cg\n");
4609 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4612 texturemode = GL_MODULATE;
4613 switch (vid.renderpath)
4615 case RENDERPATH_GL20:
4616 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4617 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4618 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4620 case RENDERPATH_CGGL:
4623 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4624 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4625 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4628 case RENDERPATH_GL13:
4629 R_Mesh_TexBind(0, first );
4630 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4631 R_Mesh_TexBind(1, second);
4633 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4635 case RENDERPATH_GL11:
4636 R_Mesh_TexBind(0, first );
4641 void R_SetupShader_DepthOrShadow(void)
4643 switch (vid.renderpath)
4645 case RENDERPATH_GL20:
4646 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4648 case RENDERPATH_CGGL:
4650 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4653 case RENDERPATH_GL13:
4654 R_Mesh_TexBind(0, 0);
4655 R_Mesh_TexBind(1, 0);
4657 case RENDERPATH_GL11:
4658 R_Mesh_TexBind(0, 0);
4663 void R_SetupShader_ShowDepth(void)
4665 switch (vid.renderpath)
4667 case RENDERPATH_GL20:
4668 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4670 case RENDERPATH_CGGL:
4672 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4675 case RENDERPATH_GL13:
4677 case RENDERPATH_GL11:
4682 extern qboolean r_shadow_usingdeferredprepass;
4683 extern cvar_t r_shadow_deferred_8bitrange;
4684 extern rtexture_t *r_shadow_attenuationgradienttexture;
4685 extern rtexture_t *r_shadow_attenuation2dtexture;
4686 extern rtexture_t *r_shadow_attenuation3dtexture;
4687 extern qboolean r_shadow_usingshadowmaprect;
4688 extern qboolean r_shadow_usingshadowmapcube;
4689 extern qboolean r_shadow_usingshadowmap2d;
4690 extern qboolean r_shadow_usingshadowmaportho;
4691 extern float r_shadow_shadowmap_texturescale[2];
4692 extern float r_shadow_shadowmap_parameters[4];
4693 extern qboolean r_shadow_shadowmapvsdct;
4694 extern qboolean r_shadow_shadowmapsampler;
4695 extern int r_shadow_shadowmappcf;
4696 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4697 extern rtexture_t *r_shadow_shadowmap2dtexture;
4698 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4699 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4700 extern matrix4x4_t r_shadow_shadowmapmatrix;
4701 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4702 extern int r_shadow_prepass_width;
4703 extern int r_shadow_prepass_height;
4704 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4705 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4706 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4707 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4708 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4710 // a blendfunc allows colormod if:
4711 // a) it can never keep the destination pixel invariant, or
4712 // b) it can keep the destination pixel invariant, and still can do so if colormodded
4713 // this is to prevent unintended side effects from colormod
4716 // IF there is a (s, sa) for which for all (d, da),
4717 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4718 // THEN, for this (s, sa) and all (colormod, d, da):
4719 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4720 // OBVIOUSLY, this means that
4721 // s*colormod * src(s*colormod, d, sa, da) = 0
4722 // dst(s*colormod, d, sa, da) = 1
4724 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4726 // main condition to leave dst color invariant:
4727 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4729 // s * 0 + d * dst(s, d, sa, da) == d
4730 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4731 // => colormod is a problem for GL_SRC_COLOR only
4733 // s + d * dst(s, d, sa, da) == d
4735 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4736 // => colormod is never problematic for these
4737 // src == GL_SRC_COLOR:
4738 // s*s + d * dst(s, d, sa, da) == d
4740 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4741 // => colormod is never problematic for these
4742 // src == GL_ONE_MINUS_SRC_COLOR:
4743 // s*(1-s) + d * dst(s, d, sa, da) == d
4744 // => s == 0 or s == 1
4745 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4746 // => colormod is a problem for GL_SRC_COLOR only
4747 // src == GL_DST_COLOR
4748 // s*d + d * dst(s, d, sa, da) == d
4750 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4751 // => colormod is always a problem
4754 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4755 // => colormod is never problematic for these
4756 // => BUT, we do not know s! We must assume it is problematic
4757 // then... except in GL_ONE case, where we know all invariant
4759 // src == GL_ONE_MINUS_DST_COLOR
4760 // s*(1-d) + d * dst(s, d, sa, da) == d
4761 // => s == 0 (1-d is impossible to handle for our desired result)
4762 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4763 // => colormod is never problematic for these
4764 // src == GL_SRC_ALPHA
4765 // s*sa + d * dst(s, d, sa, da) == d
4766 // => s == 0, or sa == 0
4767 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4768 // => colormod breaks in the case GL_SRC_COLOR only
4769 // src == GL_ONE_MINUS_SRC_ALPHA
4770 // s*(1-sa) + d * dst(s, d, sa, da) == d
4771 // => s == 0, or sa == 1
4772 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4773 // => colormod breaks in the case GL_SRC_COLOR only
4774 // src == GL_DST_ALPHA
4775 // s*da + d * dst(s, d, sa, da) == d
4777 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4778 // => colormod is never problematic for these
4783 case GL_ONE_MINUS_SRC_COLOR:
4785 case GL_ONE_MINUS_SRC_ALPHA:
4786 if(dst == GL_SRC_COLOR)
4791 case GL_ONE_MINUS_DST_COLOR:
4793 case GL_ONE_MINUS_DST_ALPHA:
4803 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4805 // select a permutation of the lighting shader appropriate to this
4806 // combination of texture, entity, light source, and fogging, only use the
4807 // minimum features necessary to avoid wasting rendering time in the
4808 // fragment shader on features that are not being used
4809 unsigned int permutation = 0;
4810 unsigned int mode = 0;
4811 qboolean allow_colormod;
4812 static float dummy_colormod[3] = {1, 1, 1};
4813 float *colormod = rsurface.colormod;
4815 if (rsurfacepass == RSURFPASS_BACKGROUND)
4817 // distorted background
4818 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4820 mode = SHADERMODE_WATER;
4821 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4822 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4823 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4824 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4826 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4828 mode = SHADERMODE_REFRACTION;
4829 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4830 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4834 mode = SHADERMODE_GENERIC;
4835 permutation |= SHADERPERMUTATION_DIFFUSE;
4836 GL_BlendFunc(GL_ONE, GL_ZERO);
4837 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4839 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4840 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4841 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4842 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4843 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4844 R_Mesh_ColorPointer(NULL, 0, 0);
4845 GL_AlphaTest(false);
4847 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4849 if (r_glsl_offsetmapping.integer)
4851 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4852 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4853 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4854 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4855 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4857 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4858 if (r_glsl_offsetmapping_reliefmapping.integer)
4859 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4862 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4863 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4864 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4865 permutation |= SHADERPERMUTATION_ALPHAKILL;
4866 // normalmap (deferred prepass), may use alpha test on diffuse
4867 mode = SHADERMODE_DEFERREDGEOMETRY;
4868 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4869 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4870 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4871 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4872 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4873 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4874 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4875 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4876 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4878 R_Mesh_ColorPointer(NULL, 0, 0);
4879 GL_AlphaTest(false);
4880 GL_BlendFunc(GL_ONE, GL_ZERO);
4881 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4883 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4885 if (r_glsl_offsetmapping.integer)
4887 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4888 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4889 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4890 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4891 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4893 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4894 if (r_glsl_offsetmapping_reliefmapping.integer)
4895 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4898 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4899 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4901 mode = SHADERMODE_LIGHTSOURCE;
4902 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4903 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4904 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4905 permutation |= SHADERPERMUTATION_CUBEFILTER;
4906 if (diffusescale > 0)
4907 permutation |= SHADERPERMUTATION_DIFFUSE;
4908 if (specularscale > 0)
4909 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4910 if (r_refdef.fogenabled)
4911 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4912 if (rsurface.texture->colormapping)
4913 permutation |= SHADERPERMUTATION_COLORMAPPING;
4914 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4916 if (r_shadow_usingshadowmaprect)
4917 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4918 if (r_shadow_usingshadowmap2d)
4919 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4920 if (r_shadow_usingshadowmapcube)
4921 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4922 else if(r_shadow_shadowmapvsdct)
4923 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4925 if (r_shadow_shadowmapsampler)
4926 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4927 if (r_shadow_shadowmappcf > 1)
4928 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4929 else if (r_shadow_shadowmappcf)
4930 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4932 if (rsurface.texture->reflectmasktexture)
4933 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4934 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4935 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4937 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4938 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4939 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4943 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4944 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4945 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4947 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4948 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4949 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4951 R_Mesh_ColorPointer(NULL, 0, 0);
4952 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4953 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4954 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4956 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4958 if (r_glsl_offsetmapping.integer)
4960 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4961 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4962 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4963 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4964 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4966 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4967 if (r_glsl_offsetmapping_reliefmapping.integer)
4968 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4971 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4972 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4973 // unshaded geometry (fullbright or ambient model lighting)
4974 mode = SHADERMODE_FLATCOLOR;
4975 ambientscale = diffusescale = specularscale = 0;
4976 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4977 permutation |= SHADERPERMUTATION_GLOW;
4978 if (r_refdef.fogenabled)
4979 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4980 if (rsurface.texture->colormapping)
4981 permutation |= SHADERPERMUTATION_COLORMAPPING;
4982 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4984 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4985 if (r_shadow_usingshadowmaprect)
4986 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4987 if (r_shadow_usingshadowmap2d)
4988 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4990 if (r_shadow_shadowmapsampler)
4991 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4992 if (r_shadow_shadowmappcf > 1)
4993 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4994 else if (r_shadow_shadowmappcf)
4995 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4997 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4998 permutation |= SHADERPERMUTATION_REFLECTION;
4999 if (rsurface.texture->reflectmasktexture)
5000 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5001 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5002 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
5004 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5005 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5006 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5010 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5011 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5012 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5014 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
5015 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5016 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5018 R_Mesh_ColorPointer(NULL, 0, 0);
5019 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5020 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5021 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5023 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5025 if (r_glsl_offsetmapping.integer)
5027 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5028 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5029 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5030 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5031 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5033 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5034 if (r_glsl_offsetmapping_reliefmapping.integer)
5035 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5038 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5039 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5040 // directional model lighting
5041 mode = SHADERMODE_LIGHTDIRECTION;
5042 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5043 permutation |= SHADERPERMUTATION_GLOW;
5044 permutation |= SHADERPERMUTATION_DIFFUSE;
5045 if (specularscale > 0)
5046 permutation |= SHADERPERMUTATION_SPECULAR;
5047 if (r_refdef.fogenabled)
5048 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5049 if (rsurface.texture->colormapping)
5050 permutation |= SHADERPERMUTATION_COLORMAPPING;
5051 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5053 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5054 if (r_shadow_usingshadowmaprect)
5055 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5056 if (r_shadow_usingshadowmap2d)
5057 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5059 if (r_shadow_shadowmapsampler)
5060 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5061 if (r_shadow_shadowmappcf > 1)
5062 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5063 else if (r_shadow_shadowmappcf)
5064 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5066 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5067 permutation |= SHADERPERMUTATION_REFLECTION;
5068 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5069 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5070 if (rsurface.texture->reflectmasktexture)
5071 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5072 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5073 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
5075 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5076 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5077 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5081 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5082 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5083 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5085 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
5086 R_Mesh_ColorPointer(NULL, 0, 0);
5087 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5088 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5089 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5091 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5093 if (r_glsl_offsetmapping.integer)
5095 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5096 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5097 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5098 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5099 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5101 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5102 if (r_glsl_offsetmapping_reliefmapping.integer)
5103 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5106 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5107 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5108 // ambient model lighting
5109 mode = SHADERMODE_LIGHTDIRECTION;
5110 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5111 permutation |= SHADERPERMUTATION_GLOW;
5112 if (r_refdef.fogenabled)
5113 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5114 if (rsurface.texture->colormapping)
5115 permutation |= SHADERPERMUTATION_COLORMAPPING;
5116 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5118 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5119 if (r_shadow_usingshadowmaprect)
5120 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5121 if (r_shadow_usingshadowmap2d)
5122 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5124 if (r_shadow_shadowmapsampler)
5125 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5126 if (r_shadow_shadowmappcf > 1)
5127 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5128 else if (r_shadow_shadowmappcf)
5129 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5131 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5132 permutation |= SHADERPERMUTATION_REFLECTION;
5133 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5134 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5135 if (rsurface.texture->reflectmasktexture)
5136 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5137 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5138 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
5140 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5141 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5142 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5146 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5147 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5148 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5150 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
5151 R_Mesh_ColorPointer(NULL, 0, 0);
5152 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5153 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5154 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5158 if (r_glsl_offsetmapping.integer)
5160 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5161 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5162 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5163 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5164 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5166 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5167 if (r_glsl_offsetmapping_reliefmapping.integer)
5168 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5171 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5172 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5174 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5175 permutation |= SHADERPERMUTATION_GLOW;
5176 if (r_refdef.fogenabled)
5177 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5178 if (rsurface.texture->colormapping)
5179 permutation |= SHADERPERMUTATION_COLORMAPPING;
5180 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5182 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5183 if (r_shadow_usingshadowmaprect)
5184 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5185 if (r_shadow_usingshadowmap2d)
5186 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5188 if (r_shadow_shadowmapsampler)
5189 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5190 if (r_shadow_shadowmappcf > 1)
5191 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5192 else if (r_shadow_shadowmappcf)
5193 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5195 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5196 permutation |= SHADERPERMUTATION_REFLECTION;
5197 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5198 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5199 if (rsurface.texture->reflectmasktexture)
5200 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5201 if (FAKELIGHT_ENABLED)
5203 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5204 mode = SHADERMODE_FAKELIGHT;
5205 permutation |= SHADERPERMUTATION_DIFFUSE;
5206 if (specularscale > 0)
5207 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5208 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5209 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5211 R_Mesh_ColorPointer(NULL, 0, 0);
5213 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5215 // deluxemapping (light direction texture)
5216 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5217 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5219 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5220 permutation |= SHADERPERMUTATION_DIFFUSE;
5221 if (specularscale > 0)
5222 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5223 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5224 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5225 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5227 R_Mesh_ColorPointer(NULL, 0, 0);
5229 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5231 // fake deluxemapping (uniform light direction in tangentspace)
5232 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5233 permutation |= SHADERPERMUTATION_DIFFUSE;
5234 if (specularscale > 0)
5235 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5236 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5237 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5238 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5240 R_Mesh_ColorPointer(NULL, 0, 0);
5242 else if (rsurface.uselightmaptexture)
5244 // ordinary lightmapping (q1bsp, q3bsp)
5245 mode = SHADERMODE_LIGHTMAP;
5246 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5247 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5248 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5250 R_Mesh_ColorPointer(NULL, 0, 0);
5254 // ordinary vertex coloring (q3bsp)
5255 mode = SHADERMODE_VERTEXCOLOR;
5256 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
5257 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5259 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5260 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
5262 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5263 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5264 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5268 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5269 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5270 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5272 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5273 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5274 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5277 colormod = dummy_colormod;
5278 switch(vid.renderpath)
5280 case RENDERPATH_GL20:
5281 R_SetupShader_SetPermutationGLSL(mode, permutation);
5282 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5283 if (mode == SHADERMODE_LIGHTSOURCE)
5285 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5286 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5287 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5288 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5289 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5290 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);
5292 // additive passes are only darkened by fog, not tinted
5293 if (r_glsl_permutation->loc_FogColor >= 0)
5294 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5295 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5299 if (mode == SHADERMODE_FLATCOLOR)
5301 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5303 else if (mode == SHADERMODE_LIGHTDIRECTION)
5305 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) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5306 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5307 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);
5308 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5309 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);
5310 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]);
5311 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]);
5315 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5316 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]);
5317 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);
5318 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5319 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);
5321 // additive passes are only darkened by fog, not tinted
5322 if (r_glsl_permutation->loc_FogColor >= 0)
5324 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5325 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5327 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5329 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);
5330 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]);
5331 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]);
5332 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5333 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5334 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5335 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5336 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5337 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2fARB(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5339 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5340 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5341 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5342 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]);
5343 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]);
5345 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5346 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5347 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5348 if (r_glsl_permutation->loc_Color_Pants >= 0)
5350 if (rsurface.texture->pantstexture)
5351 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5353 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5355 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5357 if (rsurface.texture->shirttexture)
5358 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5360 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5362 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]);
5363 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5364 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5365 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5366 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5367 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]);
5368 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5370 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5371 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5372 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5373 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5374 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5375 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5376 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5377 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5378 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5379 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5380 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5381 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5382 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5383 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5384 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5385 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5386 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5387 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white );
5388 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , r_texture_blanknormalmap );
5389 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5390 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , r_texture_white );
5391 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , r_texture_white );
5392 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5393 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5394 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5395 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5396 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5398 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5399 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture );
5400 if (rsurface.rtlight)
5402 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5403 if (r_shadow_usingshadowmapcube)
5404 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5405 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5410 case RENDERPATH_CGGL:
5412 R_SetupShader_SetPermutationCG(mode, permutation);
5413 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5414 if (mode == SHADERMODE_LIGHTSOURCE)
5416 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5417 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5421 if (mode == SHADERMODE_LIGHTDIRECTION)
5423 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
5426 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5427 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5428 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5429 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5430 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
5433 if (mode == SHADERMODE_LIGHTSOURCE)
5435 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5436 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5437 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5438 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5439 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
5441 // additive passes are only darkened by fog, not tinted
5442 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5443 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
5447 if (mode == SHADERMODE_FLATCOLOR)
5449 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5451 else if (mode == SHADERMODE_LIGHTDIRECTION)
5453 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) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);CHECKCGERROR
5454 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
5455 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
5456 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5457 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
5458 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
5459 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
5463 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
5464 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
5465 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
5466 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5467 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
5469 // additive passes are only darkened by fog, not tinted
5470 if (r_cg_permutation->fp_FogColor)
5472 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5473 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5475 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5478 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
5479 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
5480 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
5481 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5482 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5483 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5484 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5485 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
5486 if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5488 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
5489 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
5490 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5491 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));CHECKCGERROR
5492 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5493 if (r_cg_permutation->fp_Color_Pants)
5495 if (rsurface.texture->pantstexture)
5496 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5498 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5501 if (r_cg_permutation->fp_Color_Shirt)
5503 if (rsurface.texture->shirttexture)
5504 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5506 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5509 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
5510 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5511 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5512 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5513 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5514 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
5515 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5517 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
5518 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
5519 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
5520 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
5521 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
5522 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
5523 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
5524 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
5525 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
5526 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
5527 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
5528 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
5529 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
5530 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
5531 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
5532 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
5533 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
5534 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , r_texture_white );CHECKCGERROR
5535 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , r_texture_blanknormalmap );CHECKCGERROR
5536 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5537 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , r_texture_white );CHECKCGERROR
5538 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , r_texture_white );CHECKCGERROR
5539 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5540 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5541 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
5542 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
5543 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5545 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5546 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5547 if (rsurface.rtlight)
5549 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5550 if (r_shadow_usingshadowmapcube)
5551 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5552 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5559 case RENDERPATH_GL13:
5560 case RENDERPATH_GL11:
5565 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5567 // select a permutation of the lighting shader appropriate to this
5568 // combination of texture, entity, light source, and fogging, only use the
5569 // minimum features necessary to avoid wasting rendering time in the
5570 // fragment shader on features that are not being used
5571 unsigned int permutation = 0;
5572 unsigned int mode = 0;
5573 const float *lightcolorbase = rtlight->currentcolor;
5574 float ambientscale = rtlight->ambientscale;
5575 float diffusescale = rtlight->diffusescale;
5576 float specularscale = rtlight->specularscale;
5577 // this is the location of the light in view space
5578 vec3_t viewlightorigin;
5579 // this transforms from view space (camera) to light space (cubemap)
5580 matrix4x4_t viewtolight;
5581 matrix4x4_t lighttoview;
5582 float viewtolight16f[16];
5583 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5585 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5586 if (rtlight->currentcubemap != r_texture_whitecube)
5587 permutation |= SHADERPERMUTATION_CUBEFILTER;
5588 if (diffusescale > 0)
5589 permutation |= SHADERPERMUTATION_DIFFUSE;
5590 if (specularscale > 0)
5591 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5592 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5594 if (r_shadow_usingshadowmaprect)
5595 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5596 if (r_shadow_usingshadowmap2d)
5597 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5598 if (r_shadow_usingshadowmapcube)
5599 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5600 else if(r_shadow_shadowmapvsdct)
5601 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5603 if (r_shadow_shadowmapsampler)
5604 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5605 if (r_shadow_shadowmappcf > 1)
5606 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5607 else if (r_shadow_shadowmappcf)
5608 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5610 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5611 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5612 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5613 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5614 switch(vid.renderpath)
5616 case RENDERPATH_GL20:
5617 R_SetupShader_SetPermutationGLSL(mode, permutation);
5618 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5619 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5620 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);
5621 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);
5622 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);
5623 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]);
5624 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]);
5625 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) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5626 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]);
5627 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5629 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5630 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5631 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5632 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5633 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
5634 if (r_shadow_usingshadowmapcube)
5635 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5636 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5637 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5639 case RENDERPATH_CGGL:
5641 R_SetupShader_SetPermutationCG(mode, permutation);
5642 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5643 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5644 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
5645 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
5646 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
5647 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
5648 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
5649 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) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
5650 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
5651 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5653 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5654 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5655 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5656 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5657 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5658 if (r_shadow_usingshadowmapcube)
5659 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5660 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5661 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5664 case RENDERPATH_GL13:
5665 case RENDERPATH_GL11:
5670 #define SKINFRAME_HASH 1024
5674 int loadsequence; // incremented each level change
5675 memexpandablearray_t array;
5676 skinframe_t *hash[SKINFRAME_HASH];
5679 r_skinframe_t r_skinframe;
5681 void R_SkinFrame_PrepareForPurge(void)
5683 r_skinframe.loadsequence++;
5684 // wrap it without hitting zero
5685 if (r_skinframe.loadsequence >= 200)
5686 r_skinframe.loadsequence = 1;
5689 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5693 // mark the skinframe as used for the purging code
5694 skinframe->loadsequence = r_skinframe.loadsequence;
5697 void R_SkinFrame_Purge(void)
5701 for (i = 0;i < SKINFRAME_HASH;i++)
5703 for (s = r_skinframe.hash[i];s;s = s->next)
5705 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5707 if (s->merged == s->base)
5709 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5710 R_PurgeTexture(s->stain );s->stain = NULL;
5711 R_PurgeTexture(s->merged);s->merged = NULL;
5712 R_PurgeTexture(s->base );s->base = NULL;
5713 R_PurgeTexture(s->pants );s->pants = NULL;
5714 R_PurgeTexture(s->shirt );s->shirt = NULL;
5715 R_PurgeTexture(s->nmap );s->nmap = NULL;
5716 R_PurgeTexture(s->gloss );s->gloss = NULL;
5717 R_PurgeTexture(s->glow );s->glow = NULL;
5718 R_PurgeTexture(s->fog );s->fog = NULL;
5719 R_PurgeTexture(s->reflect);s->reflect = NULL;
5720 s->loadsequence = 0;
5726 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5728 char basename[MAX_QPATH];
5730 Image_StripImageExtension(name, basename, sizeof(basename));
5732 if( last == NULL ) {
5734 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5735 item = r_skinframe.hash[hashindex];
5740 // linearly search through the hash bucket
5741 for( ; item ; item = item->next ) {
5742 if( !strcmp( item->basename, basename ) ) {
5749 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5753 char basename[MAX_QPATH];
5755 Image_StripImageExtension(name, basename, sizeof(basename));
5757 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5758 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5759 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5763 rtexture_t *dyntexture;
5764 // check whether its a dynamic texture
5765 dyntexture = CL_GetDynTexture( basename );
5766 if (!add && !dyntexture)
5768 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5769 memset(item, 0, sizeof(*item));
5770 strlcpy(item->basename, basename, sizeof(item->basename));
5771 item->base = dyntexture; // either NULL or dyntexture handle
5772 item->textureflags = textureflags;
5773 item->comparewidth = comparewidth;
5774 item->compareheight = compareheight;
5775 item->comparecrc = comparecrc;
5776 item->next = r_skinframe.hash[hashindex];
5777 r_skinframe.hash[hashindex] = item;
5779 else if( item->base == NULL )
5781 rtexture_t *dyntexture;
5782 // check whether its a dynamic texture
5783 // 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]
5784 dyntexture = CL_GetDynTexture( basename );
5785 item->base = dyntexture; // either NULL or dyntexture handle
5788 R_SkinFrame_MarkUsed(item);
5792 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5794 unsigned long long avgcolor[5], wsum; \
5802 for(pix = 0; pix < cnt; ++pix) \
5805 for(comp = 0; comp < 3; ++comp) \
5807 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5810 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5812 for(comp = 0; comp < 3; ++comp) \
5813 avgcolor[comp] += getpixel * w; \
5816 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5817 avgcolor[4] += getpixel; \
5819 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5821 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5822 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5823 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5824 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5827 extern cvar_t gl_picmip;
5828 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5831 unsigned char *pixels;
5832 unsigned char *bumppixels;
5833 unsigned char *basepixels = NULL;
5834 int basepixels_width = 0;
5835 int basepixels_height = 0;
5836 skinframe_t *skinframe;
5837 rtexture_t *ddsbase = NULL;
5838 qboolean ddshasalpha = false;
5839 float ddsavgcolor[4];
5840 char basename[MAX_QPATH];
5841 int miplevel = R_PicmipForFlags(textureflags);
5842 int savemiplevel = miplevel;
5845 if (cls.state == ca_dedicated)
5848 // return an existing skinframe if already loaded
5849 // if loading of the first image fails, don't make a new skinframe as it
5850 // would cause all future lookups of this to be missing
5851 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5852 if (skinframe && skinframe->base)
5855 Image_StripImageExtension(name, basename, sizeof(basename));
5857 // check for DDS texture file first
5858 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5860 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer, &miplevel);
5861 if (basepixels == NULL)
5865 // FIXME handle miplevel
5867 if (developer_loading.integer)
5868 Con_Printf("loading skin \"%s\"\n", name);
5870 // we've got some pixels to store, so really allocate this new texture now
5872 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5873 skinframe->stain = NULL;
5874 skinframe->merged = NULL;
5875 skinframe->base = NULL;
5876 skinframe->pants = NULL;
5877 skinframe->shirt = NULL;
5878 skinframe->nmap = NULL;
5879 skinframe->gloss = NULL;
5880 skinframe->glow = NULL;
5881 skinframe->fog = NULL;
5882 skinframe->reflect = NULL;
5883 skinframe->hasalpha = false;
5887 skinframe->base = ddsbase;
5888 skinframe->hasalpha = ddshasalpha;
5889 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5890 if (r_loadfog && skinframe->hasalpha)
5891 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
5892 //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]);
5896 basepixels_width = image_width;
5897 basepixels_height = image_height;
5898 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
5899 if (textureflags & TEXF_ALPHA)
5901 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5903 if (basepixels[j] < 255)
5905 skinframe->hasalpha = true;
5909 if (r_loadfog && skinframe->hasalpha)
5911 // has transparent pixels
5912 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5913 for (j = 0;j < image_width * image_height * 4;j += 4)
5918 pixels[j+3] = basepixels[j+3];
5920 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
5924 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5925 //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]);
5926 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5927 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
5928 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5929 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
5934 mymiplevel = savemiplevel;
5935 if (r_loadnormalmap)
5936 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
5937 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5939 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5940 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5941 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5942 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5945 // _norm is the name used by tenebrae and has been adopted as standard
5946 if (r_loadnormalmap && skinframe->nmap == NULL)
5948 mymiplevel = savemiplevel;
5949 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
5951 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5955 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
5957 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5958 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5959 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5961 Mem_Free(bumppixels);
5963 else if (r_shadow_bumpscale_basetexture.value > 0)
5965 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5966 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5967 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5970 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5971 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
5974 // _luma is supported only for tenebrae compatibility
5975 // _glow is the preferred name
5976 mymiplevel = savemiplevel;
5977 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel))))
5979 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5980 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5981 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
5982 Mem_Free(pixels);pixels = NULL;
5985 mymiplevel = savemiplevel;
5986 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
5988 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5989 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5990 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
5995 mymiplevel = savemiplevel;
5996 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
5998 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5999 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6000 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6005 mymiplevel = savemiplevel;
6006 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
6008 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6009 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6010 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6015 mymiplevel = savemiplevel;
6016 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
6018 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6019 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6020 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6026 Mem_Free(basepixels);
6031 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6032 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6035 unsigned char *temp1, *temp2;
6036 skinframe_t *skinframe;
6038 if (cls.state == ca_dedicated)
6041 // if already loaded just return it, otherwise make a new skinframe
6042 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6043 if (skinframe && skinframe->base)
6046 skinframe->stain = NULL;
6047 skinframe->merged = NULL;
6048 skinframe->base = NULL;
6049 skinframe->pants = NULL;
6050 skinframe->shirt = NULL;
6051 skinframe->nmap = NULL;
6052 skinframe->gloss = NULL;
6053 skinframe->glow = NULL;
6054 skinframe->fog = NULL;
6055 skinframe->reflect = NULL;
6056 skinframe->hasalpha = false;
6058 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6062 if (developer_loading.integer)
6063 Con_Printf("loading 32bit skin \"%s\"\n", name);
6065 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6067 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6068 temp2 = temp1 + width * height * 4;
6069 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6070 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6073 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6074 if (textureflags & TEXF_ALPHA)
6076 for (i = 3;i < width * height * 4;i += 4)
6078 if (skindata[i] < 255)
6080 skinframe->hasalpha = true;
6084 if (r_loadfog && skinframe->hasalpha)
6086 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6087 memcpy(fogpixels, skindata, width * height * 4);
6088 for (i = 0;i < width * height * 4;i += 4)
6089 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6090 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6091 Mem_Free(fogpixels);
6095 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6096 //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]);
6101 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6105 skinframe_t *skinframe;
6107 if (cls.state == ca_dedicated)
6110 // if already loaded just return it, otherwise make a new skinframe
6111 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6112 if (skinframe && skinframe->base)
6115 skinframe->stain = NULL;
6116 skinframe->merged = NULL;
6117 skinframe->base = NULL;
6118 skinframe->pants = NULL;
6119 skinframe->shirt = NULL;
6120 skinframe->nmap = NULL;
6121 skinframe->gloss = NULL;
6122 skinframe->glow = NULL;
6123 skinframe->fog = NULL;
6124 skinframe->reflect = NULL;
6125 skinframe->hasalpha = false;
6127 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6131 if (developer_loading.integer)
6132 Con_Printf("loading quake skin \"%s\"\n", name);
6134 // 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)
6135 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
6136 memcpy(skinframe->qpixels, skindata, width*height);
6137 skinframe->qwidth = width;
6138 skinframe->qheight = height;
6141 for (i = 0;i < width * height;i++)
6142 featuresmask |= palette_featureflags[skindata[i]];
6144 skinframe->hasalpha = false;
6145 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6146 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6147 skinframe->qgeneratemerged = true;
6148 skinframe->qgeneratebase = skinframe->qhascolormapping;
6149 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6151 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6152 //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]);
6157 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6161 unsigned char *skindata;
6163 if (!skinframe->qpixels)
6166 if (!skinframe->qhascolormapping)
6167 colormapped = false;
6171 if (!skinframe->qgeneratebase)
6176 if (!skinframe->qgeneratemerged)
6180 width = skinframe->qwidth;
6181 height = skinframe->qheight;
6182 skindata = skinframe->qpixels;
6184 if (skinframe->qgeneratenmap)
6186 unsigned char *temp1, *temp2;
6187 skinframe->qgeneratenmap = false;
6188 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6189 temp2 = temp1 + width * height * 4;
6190 // use either a custom palette or the quake palette
6191 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6192 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6193 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6197 if (skinframe->qgenerateglow)
6199 skinframe->qgenerateglow = false;
6200 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6205 skinframe->qgeneratebase = false;
6206 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
6207 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6208 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6212 skinframe->qgeneratemerged = false;
6213 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
6216 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6218 Mem_Free(skinframe->qpixels);
6219 skinframe->qpixels = NULL;
6223 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)
6226 skinframe_t *skinframe;
6228 if (cls.state == ca_dedicated)
6231 // if already loaded just return it, otherwise make a new skinframe
6232 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6233 if (skinframe && skinframe->base)
6236 skinframe->stain = NULL;
6237 skinframe->merged = NULL;
6238 skinframe->base = NULL;
6239 skinframe->pants = NULL;
6240 skinframe->shirt = NULL;
6241 skinframe->nmap = NULL;
6242 skinframe->gloss = NULL;
6243 skinframe->glow = NULL;
6244 skinframe->fog = NULL;
6245 skinframe->reflect = NULL;
6246 skinframe->hasalpha = false;
6248 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6252 if (developer_loading.integer)
6253 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6255 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6256 if (textureflags & TEXF_ALPHA)
6258 for (i = 0;i < width * height;i++)
6260 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6262 skinframe->hasalpha = true;
6266 if (r_loadfog && skinframe->hasalpha)
6267 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6270 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6271 //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]);
6276 skinframe_t *R_SkinFrame_LoadMissing(void)
6278 skinframe_t *skinframe;
6280 if (cls.state == ca_dedicated)
6283 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6284 skinframe->stain = NULL;
6285 skinframe->merged = NULL;
6286 skinframe->base = NULL;
6287 skinframe->pants = NULL;
6288 skinframe->shirt = NULL;
6289 skinframe->nmap = NULL;
6290 skinframe->gloss = NULL;
6291 skinframe->glow = NULL;
6292 skinframe->fog = NULL;
6293 skinframe->reflect = NULL;
6294 skinframe->hasalpha = false;
6296 skinframe->avgcolor[0] = rand() / RAND_MAX;
6297 skinframe->avgcolor[1] = rand() / RAND_MAX;
6298 skinframe->avgcolor[2] = rand() / RAND_MAX;
6299 skinframe->avgcolor[3] = 1;
6304 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6305 typedef struct suffixinfo_s
6308 qboolean flipx, flipy, flipdiagonal;
6311 static suffixinfo_t suffix[3][6] =
6314 {"px", false, false, false},
6315 {"nx", false, false, false},
6316 {"py", false, false, false},
6317 {"ny", false, false, false},
6318 {"pz", false, false, false},
6319 {"nz", false, false, false}
6322 {"posx", false, false, false},
6323 {"negx", false, false, false},
6324 {"posy", false, false, false},
6325 {"negy", false, false, false},
6326 {"posz", false, false, false},
6327 {"negz", false, false, false}
6330 {"rt", true, false, true},
6331 {"lf", false, true, true},
6332 {"ft", true, true, false},
6333 {"bk", false, false, false},
6334 {"up", true, false, true},
6335 {"dn", true, false, true}
6339 static int componentorder[4] = {0, 1, 2, 3};
6341 rtexture_t *R_LoadCubemap(const char *basename)
6343 int i, j, cubemapsize;
6344 unsigned char *cubemappixels, *image_buffer;
6345 rtexture_t *cubemaptexture;
6347 // must start 0 so the first loadimagepixels has no requested width/height
6349 cubemappixels = NULL;
6350 cubemaptexture = NULL;
6351 // keep trying different suffix groups (posx, px, rt) until one loads
6352 for (j = 0;j < 3 && !cubemappixels;j++)
6354 // load the 6 images in the suffix group
6355 for (i = 0;i < 6;i++)
6357 // generate an image name based on the base and and suffix
6358 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6360 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer, NULL)))
6362 // an image loaded, make sure width and height are equal
6363 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6365 // if this is the first image to load successfully, allocate the cubemap memory
6366 if (!cubemappixels && image_width >= 1)
6368 cubemapsize = image_width;
6369 // note this clears to black, so unavailable sides are black
6370 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6372 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6374 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);
6377 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6379 Mem_Free(image_buffer);
6383 // if a cubemap loaded, upload it
6386 if (developer_loading.integer)
6387 Con_Printf("loading cubemap \"%s\"\n", basename);
6389 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6390 Mem_Free(cubemappixels);
6394 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6395 if (developer_loading.integer)
6397 Con_Printf("(tried tried images ");
6398 for (j = 0;j < 3;j++)
6399 for (i = 0;i < 6;i++)
6400 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6401 Con_Print(" and was unable to find any of them).\n");
6404 return cubemaptexture;
6407 rtexture_t *R_GetCubemap(const char *basename)
6410 for (i = 0;i < r_texture_numcubemaps;i++)
6411 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6412 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6413 if (i >= MAX_CUBEMAPS)
6414 return r_texture_whitecube;
6415 r_texture_numcubemaps++;
6416 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6417 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6418 return r_texture_cubemaps[i].texture;
6421 void R_FreeCubemaps(void)
6424 for (i = 0;i < r_texture_numcubemaps;i++)
6426 if (developer_loading.integer)
6427 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6428 if (r_texture_cubemaps[i].texture)
6429 R_FreeTexture(r_texture_cubemaps[i].texture);
6431 r_texture_numcubemaps = 0;
6434 void R_Main_FreeViewCache(void)
6436 if (r_refdef.viewcache.entityvisible)
6437 Mem_Free(r_refdef.viewcache.entityvisible);
6438 if (r_refdef.viewcache.world_pvsbits)
6439 Mem_Free(r_refdef.viewcache.world_pvsbits);
6440 if (r_refdef.viewcache.world_leafvisible)
6441 Mem_Free(r_refdef.viewcache.world_leafvisible);
6442 if (r_refdef.viewcache.world_surfacevisible)
6443 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6444 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6447 void R_Main_ResizeViewCache(void)
6449 int numentities = r_refdef.scene.numentities;
6450 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6451 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6452 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6453 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6454 if (r_refdef.viewcache.maxentities < numentities)
6456 r_refdef.viewcache.maxentities = numentities;
6457 if (r_refdef.viewcache.entityvisible)
6458 Mem_Free(r_refdef.viewcache.entityvisible);
6459 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6461 if (r_refdef.viewcache.world_numclusters != numclusters)
6463 r_refdef.viewcache.world_numclusters = numclusters;
6464 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6465 if (r_refdef.viewcache.world_pvsbits)
6466 Mem_Free(r_refdef.viewcache.world_pvsbits);
6467 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6469 if (r_refdef.viewcache.world_numleafs != numleafs)
6471 r_refdef.viewcache.world_numleafs = numleafs;
6472 if (r_refdef.viewcache.world_leafvisible)
6473 Mem_Free(r_refdef.viewcache.world_leafvisible);
6474 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6476 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6478 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6479 if (r_refdef.viewcache.world_surfacevisible)
6480 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6481 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6485 extern rtexture_t *loadingscreentexture;
6486 void gl_main_start(void)
6488 loadingscreentexture = NULL;
6489 r_texture_blanknormalmap = NULL;
6490 r_texture_white = NULL;
6491 r_texture_grey128 = NULL;
6492 r_texture_black = NULL;
6493 r_texture_whitecube = NULL;
6494 r_texture_normalizationcube = NULL;
6495 r_texture_fogattenuation = NULL;
6496 r_texture_fogheighttexture = NULL;
6497 r_texture_gammaramps = NULL;
6498 r_texture_numcubemaps = 0;
6500 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6501 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6503 switch(vid.renderpath)
6505 case RENDERPATH_GL20:
6506 case RENDERPATH_CGGL:
6507 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6508 Cvar_SetValueQuick(&gl_combine, 1);
6509 Cvar_SetValueQuick(&r_glsl, 1);
6510 r_loadnormalmap = true;
6514 case RENDERPATH_GL13:
6515 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6516 Cvar_SetValueQuick(&gl_combine, 1);
6517 Cvar_SetValueQuick(&r_glsl, 0);
6518 r_loadnormalmap = false;
6519 r_loadgloss = false;
6522 case RENDERPATH_GL11:
6523 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6524 Cvar_SetValueQuick(&gl_combine, 0);
6525 Cvar_SetValueQuick(&r_glsl, 0);
6526 r_loadnormalmap = false;
6527 r_loadgloss = false;
6533 R_FrameData_Reset();
6537 memset(r_queries, 0, sizeof(r_queries));
6539 r_qwskincache = NULL;
6540 r_qwskincache_size = 0;
6542 // set up r_skinframe loading system for textures
6543 memset(&r_skinframe, 0, sizeof(r_skinframe));
6544 r_skinframe.loadsequence = 1;
6545 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6547 r_main_texturepool = R_AllocTexturePool();
6548 R_BuildBlankTextures();
6550 if (vid.support.arb_texture_cube_map)
6553 R_BuildNormalizationCube();
6555 r_texture_fogattenuation = NULL;
6556 r_texture_fogheighttexture = NULL;
6557 r_texture_gammaramps = NULL;
6558 //r_texture_fogintensity = NULL;
6559 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6560 memset(&r_waterstate, 0, sizeof(r_waterstate));
6561 r_glsl_permutation = NULL;
6562 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6563 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6564 glslshaderstring = NULL;
6566 r_cg_permutation = NULL;
6567 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6568 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6569 cgshaderstring = NULL;
6571 memset(&r_svbsp, 0, sizeof (r_svbsp));
6573 r_refdef.fogmasktable_density = 0;
6576 void gl_main_shutdown(void)
6579 R_FrameData_Reset();
6581 R_Main_FreeViewCache();
6584 qglDeleteQueriesARB(r_maxqueries, r_queries);
6588 memset(r_queries, 0, sizeof(r_queries));
6590 r_qwskincache = NULL;
6591 r_qwskincache_size = 0;
6593 // clear out the r_skinframe state
6594 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6595 memset(&r_skinframe, 0, sizeof(r_skinframe));
6598 Mem_Free(r_svbsp.nodes);
6599 memset(&r_svbsp, 0, sizeof (r_svbsp));
6600 R_FreeTexturePool(&r_main_texturepool);
6601 loadingscreentexture = NULL;
6602 r_texture_blanknormalmap = NULL;
6603 r_texture_white = NULL;
6604 r_texture_grey128 = NULL;
6605 r_texture_black = NULL;
6606 r_texture_whitecube = NULL;
6607 r_texture_normalizationcube = NULL;
6608 r_texture_fogattenuation = NULL;
6609 r_texture_fogheighttexture = NULL;
6610 r_texture_gammaramps = NULL;
6611 r_texture_numcubemaps = 0;
6612 //r_texture_fogintensity = NULL;
6613 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6614 memset(&r_waterstate, 0, sizeof(r_waterstate));
6615 r_glsl_permutation = NULL;
6616 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6617 glslshaderstring = NULL;
6619 r_cg_permutation = NULL;
6620 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6621 cgshaderstring = NULL;
6626 extern void CL_ParseEntityLump(char *entitystring);
6627 void gl_main_newmap(void)
6629 // FIXME: move this code to client
6630 char *entities, entname[MAX_QPATH];
6632 Mem_Free(r_qwskincache);
6633 r_qwskincache = NULL;
6634 r_qwskincache_size = 0;
6637 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6638 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6640 CL_ParseEntityLump(entities);
6644 if (cl.worldmodel->brush.entities)
6645 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6647 R_Main_FreeViewCache();
6649 R_FrameData_Reset();
6652 void GL_Main_Init(void)
6654 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6656 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6657 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6658 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6659 if (gamemode == GAME_NEHAHRA)
6661 Cvar_RegisterVariable (&gl_fogenable);
6662 Cvar_RegisterVariable (&gl_fogdensity);
6663 Cvar_RegisterVariable (&gl_fogred);
6664 Cvar_RegisterVariable (&gl_foggreen);
6665 Cvar_RegisterVariable (&gl_fogblue);
6666 Cvar_RegisterVariable (&gl_fogstart);
6667 Cvar_RegisterVariable (&gl_fogend);
6668 Cvar_RegisterVariable (&gl_skyclip);
6670 Cvar_RegisterVariable(&r_motionblur);
6671 Cvar_RegisterVariable(&r_motionblur_maxblur);
6672 Cvar_RegisterVariable(&r_motionblur_bmin);
6673 Cvar_RegisterVariable(&r_motionblur_vmin);
6674 Cvar_RegisterVariable(&r_motionblur_vmax);
6675 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6676 Cvar_RegisterVariable(&r_motionblur_randomize);
6677 Cvar_RegisterVariable(&r_damageblur);
6678 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6679 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6680 Cvar_RegisterVariable(&r_equalize_entities_by);
6681 Cvar_RegisterVariable(&r_equalize_entities_to);
6682 Cvar_RegisterVariable(&r_depthfirst);
6683 Cvar_RegisterVariable(&r_useinfinitefarclip);
6684 Cvar_RegisterVariable(&r_farclip_base);
6685 Cvar_RegisterVariable(&r_farclip_world);
6686 Cvar_RegisterVariable(&r_nearclip);
6687 Cvar_RegisterVariable(&r_showbboxes);
6688 Cvar_RegisterVariable(&r_showsurfaces);
6689 Cvar_RegisterVariable(&r_showtris);
6690 Cvar_RegisterVariable(&r_shownormals);
6691 Cvar_RegisterVariable(&r_showlighting);
6692 Cvar_RegisterVariable(&r_showshadowvolumes);
6693 Cvar_RegisterVariable(&r_showcollisionbrushes);
6694 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6695 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6696 Cvar_RegisterVariable(&r_showdisabledepthtest);
6697 Cvar_RegisterVariable(&r_drawportals);
6698 Cvar_RegisterVariable(&r_drawentities);
6699 Cvar_RegisterVariable(&r_draw2d);
6700 Cvar_RegisterVariable(&r_drawworld);
6701 Cvar_RegisterVariable(&r_cullentities_trace);
6702 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6703 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6704 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6705 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6706 Cvar_RegisterVariable(&r_drawviewmodel);
6707 Cvar_RegisterVariable(&r_drawexteriormodel);
6708 Cvar_RegisterVariable(&r_speeds);
6709 Cvar_RegisterVariable(&r_fullbrights);
6710 Cvar_RegisterVariable(&r_wateralpha);
6711 Cvar_RegisterVariable(&r_dynamic);
6712 Cvar_RegisterVariable(&r_fakelight);
6713 Cvar_RegisterVariable(&r_fakelight_intensity);
6714 Cvar_RegisterVariable(&r_fullbright);
6715 Cvar_RegisterVariable(&r_shadows);
6716 Cvar_RegisterVariable(&r_shadows_darken);
6717 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6718 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6719 Cvar_RegisterVariable(&r_shadows_throwdistance);
6720 Cvar_RegisterVariable(&r_shadows_throwdirection);
6721 Cvar_RegisterVariable(&r_shadows_focus);
6722 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6723 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6724 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6725 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6726 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6727 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6728 Cvar_RegisterVariable(&r_fog_exp2);
6729 Cvar_RegisterVariable(&r_drawfog);
6730 Cvar_RegisterVariable(&r_transparentdepthmasking);
6731 Cvar_RegisterVariable(&r_texture_dds_load);
6732 Cvar_RegisterVariable(&r_texture_dds_save);
6733 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6734 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6735 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6736 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6737 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6738 Cvar_RegisterVariable(&r_textureunits);
6739 Cvar_RegisterVariable(&gl_combine);
6740 Cvar_RegisterVariable(&r_glsl);
6741 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6742 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6743 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6744 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6745 Cvar_RegisterVariable(&r_glsl_postprocess);
6746 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6747 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6748 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6749 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6750 Cvar_RegisterVariable(&r_water);
6751 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6752 Cvar_RegisterVariable(&r_water_clippingplanebias);
6753 Cvar_RegisterVariable(&r_water_refractdistort);
6754 Cvar_RegisterVariable(&r_water_reflectdistort);
6755 Cvar_RegisterVariable(&r_water_scissormode);
6756 Cvar_RegisterVariable(&r_lerpsprites);
6757 Cvar_RegisterVariable(&r_lerpmodels);
6758 Cvar_RegisterVariable(&r_lerplightstyles);
6759 Cvar_RegisterVariable(&r_waterscroll);
6760 Cvar_RegisterVariable(&r_bloom);
6761 Cvar_RegisterVariable(&r_bloom_colorscale);
6762 Cvar_RegisterVariable(&r_bloom_brighten);
6763 Cvar_RegisterVariable(&r_bloom_blur);
6764 Cvar_RegisterVariable(&r_bloom_resolution);
6765 Cvar_RegisterVariable(&r_bloom_colorexponent);
6766 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6767 Cvar_RegisterVariable(&r_hdr);
6768 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6769 Cvar_RegisterVariable(&r_hdr_glowintensity);
6770 Cvar_RegisterVariable(&r_hdr_range);
6771 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6772 Cvar_RegisterVariable(&developer_texturelogging);
6773 Cvar_RegisterVariable(&gl_lightmaps);
6774 Cvar_RegisterVariable(&r_test);
6775 Cvar_RegisterVariable(&r_batchmode);
6776 Cvar_RegisterVariable(&r_glsl_saturation);
6777 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6778 Cvar_RegisterVariable(&r_framedatasize);
6779 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6780 Cvar_SetValue("r_fullbrights", 0);
6781 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6783 Cvar_RegisterVariable(&r_track_sprites);
6784 Cvar_RegisterVariable(&r_track_sprites_flags);
6785 Cvar_RegisterVariable(&r_track_sprites_scalew);
6786 Cvar_RegisterVariable(&r_track_sprites_scaleh);
6787 Cvar_RegisterVariable(&r_overheadsprites_perspective);
6788 Cvar_RegisterVariable(&r_overheadsprites_pushback);
6791 extern void R_Textures_Init(void);
6792 extern void GL_Draw_Init(void);
6793 extern void GL_Main_Init(void);
6794 extern void R_Shadow_Init(void);
6795 extern void R_Sky_Init(void);
6796 extern void GL_Surf_Init(void);
6797 extern void R_Particles_Init(void);
6798 extern void R_Explosion_Init(void);
6799 extern void gl_backend_init(void);
6800 extern void Sbar_Init(void);
6801 extern void R_LightningBeams_Init(void);
6802 extern void Mod_RenderInit(void);
6803 extern void Font_Init(void);
6805 void Render_Init(void)
6818 R_LightningBeams_Init();
6827 extern char *ENGINE_EXTENSIONS;
6830 gl_renderer = (const char *)qglGetString(GL_RENDERER);
6831 gl_vendor = (const char *)qglGetString(GL_VENDOR);
6832 gl_version = (const char *)qglGetString(GL_VERSION);
6833 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6837 if (!gl_platformextensions)
6838 gl_platformextensions = "";
6840 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6841 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6842 Con_Printf("GL_VERSION: %s\n", gl_version);
6843 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6844 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6846 VID_CheckExtensions();
6848 // LordHavoc: report supported extensions
6849 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6851 // clear to black (loading plaque will be seen over this)
6853 qglClearColor(0,0,0,1);CHECKGLERROR
6854 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6857 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6861 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6863 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6866 p = r_refdef.view.frustum + i;
6871 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6875 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6879 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6883 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6887 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6891 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6895 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6899 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6907 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6911 for (i = 0;i < numplanes;i++)
6918 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6922 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6926 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6930 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6934 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6938 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6942 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6946 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6954 //==================================================================================
6956 // LordHavoc: this stores temporary data used within the same frame
6958 qboolean r_framedata_failed;
6959 static size_t r_framedata_size;
6960 static size_t r_framedata_current;
6961 static void *r_framedata_base;
6963 void R_FrameData_Reset(void)
6965 if (r_framedata_base)
6966 Mem_Free(r_framedata_base);
6967 r_framedata_base = NULL;
6968 r_framedata_size = 0;
6969 r_framedata_current = 0;
6970 r_framedata_failed = false;
6973 void R_FrameData_NewFrame(void)
6976 if (r_framedata_failed)
6977 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6978 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6979 wantedsize = bound(65536, wantedsize, 128*1024*1024);
6980 if (r_framedata_size != wantedsize)
6982 r_framedata_size = wantedsize;
6983 if (r_framedata_base)
6984 Mem_Free(r_framedata_base);
6985 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6987 r_framedata_current = 0;
6988 r_framedata_failed = false;
6991 void *R_FrameData_Alloc(size_t size)
6995 // align to 16 byte boundary
6996 size = (size + 15) & ~15;
6997 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6998 r_framedata_current += size;
7001 if (r_framedata_current > r_framedata_size)
7002 r_framedata_failed = true;
7004 // return NULL on everything after a failure
7005 if (r_framedata_failed)
7011 void *R_FrameData_Store(size_t size, void *data)
7013 void *d = R_FrameData_Alloc(size);
7015 memcpy(d, data, size);
7019 //==================================================================================
7021 // LordHavoc: animcache originally written by Echon, rewritten since then
7024 * Animation cache prevents re-generating mesh data for an animated model
7025 * multiple times in one frame for lighting, shadowing, reflections, etc.
7028 void R_AnimCache_Free(void)
7032 void R_AnimCache_ClearCache(void)
7035 entity_render_t *ent;
7037 for (i = 0;i < r_refdef.scene.numentities;i++)
7039 ent = r_refdef.scene.entities[i];
7040 ent->animcache_vertex3f = NULL;
7041 ent->animcache_normal3f = NULL;
7042 ent->animcache_svector3f = NULL;
7043 ent->animcache_tvector3f = NULL;
7047 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7049 dp_model_t *model = ent->model;
7051 // see if it's already cached this frame
7052 if (ent->animcache_vertex3f)
7054 // add normals/tangents if needed
7055 if (wantnormals || wanttangents)
7057 if (ent->animcache_normal3f)
7058 wantnormals = false;
7059 if (ent->animcache_svector3f)
7060 wanttangents = false;
7061 if (wantnormals || wanttangents)
7063 numvertices = model->surfmesh.num_vertices;
7065 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7068 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7069 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7071 if (!r_framedata_failed)
7072 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7078 // see if this ent is worth caching
7079 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7081 // get some memory for this entity and generate mesh data
7082 numvertices = model->surfmesh.num_vertices;
7083 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7085 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7088 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7089 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7091 if (!r_framedata_failed)
7092 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7094 return !r_framedata_failed;
7097 void R_AnimCache_CacheVisibleEntities(void)
7100 qboolean wantnormals = !r_showsurfaces.integer;
7101 qboolean wanttangents = !r_showsurfaces.integer;
7103 switch(vid.renderpath)
7105 case RENDERPATH_GL20:
7106 case RENDERPATH_CGGL:
7108 case RENDERPATH_GL13:
7109 case RENDERPATH_GL11:
7110 wanttangents = false;
7114 // TODO: thread this
7115 // NOTE: R_PrepareRTLights() also caches entities
7117 for (i = 0;i < r_refdef.scene.numentities;i++)
7118 if (r_refdef.viewcache.entityvisible[i])
7119 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7122 //==================================================================================
7124 static void R_View_UpdateEntityLighting (void)
7127 entity_render_t *ent;
7128 vec3_t tempdiffusenormal, avg;
7129 vec_t f, fa, fd, fdd;
7130 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7132 for (i = 0;i < r_refdef.scene.numentities;i++)
7134 ent = r_refdef.scene.entities[i];
7136 // skip unseen models
7137 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7141 if (ent->model && ent->model->brush.num_leafs)
7143 // TODO: use modellight for r_ambient settings on world?
7144 VectorSet(ent->modellight_ambient, 0, 0, 0);
7145 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7146 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7150 // fetch the lighting from the worldmodel data
7151 VectorClear(ent->modellight_ambient);
7152 VectorClear(ent->modellight_diffuse);
7153 VectorClear(tempdiffusenormal);
7154 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7157 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7159 // complete lightning for lit sprites
7160 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7161 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7163 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7164 org[2] = org[2] + r_overheadsprites_pushback.value;
7165 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, true, true);
7168 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7170 if(ent->flags & RENDER_EQUALIZE)
7172 // first fix up ambient lighting...
7173 if(r_equalize_entities_minambient.value > 0)
7175 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7178 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7179 if(fa < r_equalize_entities_minambient.value * fd)
7182 // fa'/fd' = minambient
7183 // fa'+0.25*fd' = fa+0.25*fd
7185 // fa' = fd' * minambient
7186 // fd'*(0.25+minambient) = fa+0.25*fd
7188 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7189 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7191 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7192 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
7193 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7194 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7199 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7201 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7202 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7205 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7206 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7207 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7213 VectorSet(ent->modellight_ambient, 1, 1, 1);
7215 // move the light direction into modelspace coordinates for lighting code
7216 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7217 if(VectorLength2(ent->modellight_lightdir) == 0)
7218 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7219 VectorNormalize(ent->modellight_lightdir);
7223 #define MAX_LINEOFSIGHTTRACES 64
7225 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7228 vec3_t boxmins, boxmaxs;
7231 dp_model_t *model = r_refdef.scene.worldmodel;
7233 if (!model || !model->brush.TraceLineOfSight)
7236 // expand the box a little
7237 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7238 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7239 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7240 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7241 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7242 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7244 // return true if eye is inside enlarged box
7245 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7249 VectorCopy(eye, start);
7250 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7251 if (model->brush.TraceLineOfSight(model, start, end))
7254 // try various random positions
7255 for (i = 0;i < numsamples;i++)
7257 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7258 if (model->brush.TraceLineOfSight(model, start, end))
7266 static void R_View_UpdateEntityVisible (void)
7271 entity_render_t *ent;
7273 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7274 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7275 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7276 : RENDER_EXTERIORMODEL;
7277 if (!r_drawviewmodel.integer)
7278 renderimask |= RENDER_VIEWMODEL;
7279 if (!r_drawexteriormodel.integer)
7280 renderimask |= RENDER_EXTERIORMODEL;
7281 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7283 // worldmodel can check visibility
7284 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7285 for (i = 0;i < r_refdef.scene.numentities;i++)
7287 ent = r_refdef.scene.entities[i];
7288 if (!(ent->flags & renderimask))
7289 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
7290 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))
7291 r_refdef.viewcache.entityvisible[i] = true;
7293 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7294 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7296 for (i = 0;i < r_refdef.scene.numentities;i++)
7298 ent = r_refdef.scene.entities[i];
7299 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7301 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7303 continue; // temp entities do pvs only
7304 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7305 ent->last_trace_visibility = realtime;
7306 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7307 r_refdef.viewcache.entityvisible[i] = 0;
7314 // no worldmodel or it can't check visibility
7315 for (i = 0;i < r_refdef.scene.numentities;i++)
7317 ent = r_refdef.scene.entities[i];
7318 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));
7323 /// only used if skyrendermasked, and normally returns false
7324 int R_DrawBrushModelsSky (void)
7327 entity_render_t *ent;
7330 for (i = 0;i < r_refdef.scene.numentities;i++)
7332 if (!r_refdef.viewcache.entityvisible[i])
7334 ent = r_refdef.scene.entities[i];
7335 if (!ent->model || !ent->model->DrawSky)
7337 ent->model->DrawSky(ent);
7343 static void R_DrawNoModel(entity_render_t *ent);
7344 static void R_DrawModels(void)
7347 entity_render_t *ent;
7349 for (i = 0;i < r_refdef.scene.numentities;i++)
7351 if (!r_refdef.viewcache.entityvisible[i])
7353 ent = r_refdef.scene.entities[i];
7354 r_refdef.stats.entities++;
7355 if (ent->model && ent->model->Draw != NULL)
7356 ent->model->Draw(ent);
7362 static void R_DrawModelsDepth(void)
7365 entity_render_t *ent;
7367 for (i = 0;i < r_refdef.scene.numentities;i++)
7369 if (!r_refdef.viewcache.entityvisible[i])
7371 ent = r_refdef.scene.entities[i];
7372 if (ent->model && ent->model->DrawDepth != NULL)
7373 ent->model->DrawDepth(ent);
7377 static void R_DrawModelsDebug(void)
7380 entity_render_t *ent;
7382 for (i = 0;i < r_refdef.scene.numentities;i++)
7384 if (!r_refdef.viewcache.entityvisible[i])
7386 ent = r_refdef.scene.entities[i];
7387 if (ent->model && ent->model->DrawDebug != NULL)
7388 ent->model->DrawDebug(ent);
7392 static void R_DrawModelsAddWaterPlanes(void)
7395 entity_render_t *ent;
7397 for (i = 0;i < r_refdef.scene.numentities;i++)
7399 if (!r_refdef.viewcache.entityvisible[i])
7401 ent = r_refdef.scene.entities[i];
7402 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7403 ent->model->DrawAddWaterPlanes(ent);
7407 static void R_View_SetFrustum(const int *scissor)
7410 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7411 vec3_t forward, left, up, origin, v;
7415 // flipped x coordinates (because x points left here)
7416 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7417 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7419 // non-flipped y coordinates
7420 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7421 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7424 // we can't trust r_refdef.view.forward and friends in reflected scenes
7425 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7428 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7429 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7430 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7431 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7432 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7433 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7434 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7435 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7436 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7437 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7438 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7439 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7443 zNear = r_refdef.nearclip;
7444 nudge = 1.0 - 1.0 / (1<<23);
7445 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7446 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7447 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7448 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7449 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7450 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7451 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7452 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7458 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7459 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7460 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7461 r_refdef.view.frustum[0].dist = m[15] - m[12];
7463 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7464 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7465 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7466 r_refdef.view.frustum[1].dist = m[15] + m[12];
7468 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7469 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7470 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7471 r_refdef.view.frustum[2].dist = m[15] - m[13];
7473 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7474 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7475 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7476 r_refdef.view.frustum[3].dist = m[15] + m[13];
7478 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7479 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7480 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7481 r_refdef.view.frustum[4].dist = m[15] - m[14];
7483 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7484 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7485 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7486 r_refdef.view.frustum[5].dist = m[15] + m[14];
7489 if (r_refdef.view.useperspective)
7491 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7492 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
7493 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
7494 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
7495 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
7497 // then the normals from the corners relative to origin
7498 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7499 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7500 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7501 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7503 // in a NORMAL view, forward cross left == up
7504 // in a REFLECTED view, forward cross left == down
7505 // so our cross products above need to be adjusted for a left handed coordinate system
7506 CrossProduct(forward, left, v);
7507 if(DotProduct(v, up) < 0)
7509 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7510 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7511 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7512 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7515 // Leaving those out was a mistake, those were in the old code, and they
7516 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7517 // I couldn't reproduce it after adding those normalizations. --blub
7518 VectorNormalize(r_refdef.view.frustum[0].normal);
7519 VectorNormalize(r_refdef.view.frustum[1].normal);
7520 VectorNormalize(r_refdef.view.frustum[2].normal);
7521 VectorNormalize(r_refdef.view.frustum[3].normal);
7523 // make the corners absolute
7524 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7525 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7526 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7527 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7530 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7532 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7533 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7534 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7535 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7536 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7540 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7541 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7542 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7543 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7544 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7545 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7546 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7547 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7548 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7549 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7551 r_refdef.view.numfrustumplanes = 5;
7553 if (r_refdef.view.useclipplane)
7555 r_refdef.view.numfrustumplanes = 6;
7556 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7559 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7560 PlaneClassify(r_refdef.view.frustum + i);
7562 // LordHavoc: note to all quake engine coders, Quake had a special case
7563 // for 90 degrees which assumed a square view (wrong), so I removed it,
7564 // Quake2 has it disabled as well.
7566 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7567 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7568 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7569 //PlaneClassify(&frustum[0]);
7571 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7572 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7573 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7574 //PlaneClassify(&frustum[1]);
7576 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7577 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7578 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7579 //PlaneClassify(&frustum[2]);
7581 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7582 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7583 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7584 //PlaneClassify(&frustum[3]);
7587 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7588 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7589 //PlaneClassify(&frustum[4]);
7592 void R_View_UpdateWithScissor(const int *myscissor)
7594 R_Main_ResizeViewCache();
7595 R_View_SetFrustum(myscissor);
7596 R_View_WorldVisibility(r_refdef.view.useclipplane);
7597 R_View_UpdateEntityVisible();
7598 R_View_UpdateEntityLighting();
7601 void R_View_Update(void)
7603 R_Main_ResizeViewCache();
7604 R_View_SetFrustum(NULL);
7605 R_View_WorldVisibility(r_refdef.view.useclipplane);
7606 R_View_UpdateEntityVisible();
7607 R_View_UpdateEntityLighting();
7610 void R_SetupView(qboolean allowwaterclippingplane)
7612 const float *customclipplane = NULL;
7614 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7616 // LordHavoc: couldn't figure out how to make this approach the
7617 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7618 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7619 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7620 dist = r_refdef.view.clipplane.dist;
7621 plane[0] = r_refdef.view.clipplane.normal[0];
7622 plane[1] = r_refdef.view.clipplane.normal[1];
7623 plane[2] = r_refdef.view.clipplane.normal[2];
7625 customclipplane = plane;
7628 if (!r_refdef.view.useperspective)
7629 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);
7630 else if (vid.stencil && r_useinfinitefarclip.integer)
7631 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);
7633 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);
7634 R_SetViewport(&r_refdef.view.viewport);
7637 void R_EntityMatrix(const matrix4x4_t *matrix)
7639 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7641 gl_modelmatrixchanged = false;
7642 gl_modelmatrix = *matrix;
7643 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7644 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7645 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7646 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7648 switch(vid.renderpath)
7650 case RENDERPATH_GL20:
7651 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7652 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7653 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7655 case RENDERPATH_CGGL:
7658 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7659 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7660 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7663 case RENDERPATH_GL13:
7664 case RENDERPATH_GL11:
7665 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7671 void R_ResetViewRendering2D(void)
7673 r_viewport_t viewport;
7676 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7677 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);
7678 R_SetViewport(&viewport);
7679 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7680 GL_Color(1, 1, 1, 1);
7681 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7682 GL_BlendFunc(GL_ONE, GL_ZERO);
7683 GL_AlphaTest(false);
7684 GL_ScissorTest(false);
7685 GL_DepthMask(false);
7686 GL_DepthRange(0, 1);
7687 GL_DepthTest(false);
7688 R_EntityMatrix(&identitymatrix);
7689 R_Mesh_ResetTextureState();
7690 GL_PolygonOffset(0, 0);
7691 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7692 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7693 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7694 qglStencilMask(~0);CHECKGLERROR
7695 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7696 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7697 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7700 void R_ResetViewRendering3D(void)
7705 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7706 GL_Color(1, 1, 1, 1);
7707 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7708 GL_BlendFunc(GL_ONE, GL_ZERO);
7709 GL_AlphaTest(false);
7710 GL_ScissorTest(true);
7712 GL_DepthRange(0, 1);
7714 R_EntityMatrix(&identitymatrix);
7715 R_Mesh_ResetTextureState();
7716 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7717 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7718 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7719 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7720 qglStencilMask(~0);CHECKGLERROR
7721 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7722 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7723 GL_CullFace(r_refdef.view.cullface_back);
7728 R_RenderView_UpdateViewVectors
7731 static void R_RenderView_UpdateViewVectors(void)
7733 // break apart the view matrix into vectors for various purposes
7734 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7735 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7736 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7737 VectorNegate(r_refdef.view.left, r_refdef.view.right);
7738 // make an inverted copy of the view matrix for tracking sprites
7739 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7742 void R_RenderScene(void);
7743 void R_RenderWaterPlanes(void);
7745 static void R_Water_StartFrame(void)
7748 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
7749 r_waterstate_waterplane_t *p;
7751 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7754 switch(vid.renderpath)
7756 case RENDERPATH_GL20:
7757 case RENDERPATH_CGGL:
7759 case RENDERPATH_GL13:
7760 case RENDERPATH_GL11:
7764 // set waterwidth and waterheight to the water resolution that will be
7765 // used (often less than the screen resolution for faster rendering)
7766 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7767 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7769 // calculate desired texture sizes
7770 // can't use water if the card does not support the texture size
7771 if (!r_water.integer || r_showsurfaces.integer)
7772 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
7773 else if (vid.support.arb_texture_non_power_of_two)
7775 texturewidth = waterwidth;
7776 textureheight = waterheight;
7777 camerawidth = waterwidth;
7778 cameraheight = waterheight;
7782 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
7783 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
7784 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
7785 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
7788 // allocate textures as needed
7789 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
7791 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7792 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7794 if (p->texture_refraction)
7795 R_FreeTexture(p->texture_refraction);
7796 p->texture_refraction = NULL;
7797 if (p->texture_reflection)
7798 R_FreeTexture(p->texture_reflection);
7799 p->texture_reflection = NULL;
7800 if (p->texture_camera)
7801 R_FreeTexture(p->texture_camera);
7802 p->texture_camera = NULL;
7804 memset(&r_waterstate, 0, sizeof(r_waterstate));
7805 r_waterstate.texturewidth = texturewidth;
7806 r_waterstate.textureheight = textureheight;
7807 r_waterstate.camerawidth = camerawidth;
7808 r_waterstate.cameraheight = cameraheight;
7811 if (r_waterstate.texturewidth)
7813 r_waterstate.enabled = true;
7815 // when doing a reduced render (HDR) we want to use a smaller area
7816 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7817 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7819 // set up variables that will be used in shader setup
7820 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7821 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7822 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7823 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7826 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7827 r_waterstate.numwaterplanes = 0;
7830 void R_Water_AddWaterPlane(msurface_t *surface)
7832 int triangleindex, planeindex;
7839 r_waterstate_waterplane_t *p;
7840 texture_t *t = R_GetCurrentTexture(surface->texture);
7841 cam_ent = t->camera_entity;
7842 if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
7845 // just use the first triangle with a valid normal for any decisions
7846 VectorClear(normal);
7847 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7849 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7850 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7851 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7852 TriangleNormal(vert[0], vert[1], vert[2], normal);
7853 if (VectorLength2(normal) >= 0.001)
7857 VectorCopy(normal, plane.normal);
7858 VectorNormalize(plane.normal);
7859 plane.dist = DotProduct(vert[0], plane.normal);
7860 PlaneClassify(&plane);
7861 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7863 // skip backfaces (except if nocullface is set)
7864 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7866 VectorNegate(plane.normal, plane.normal);
7868 PlaneClassify(&plane);
7872 // find a matching plane if there is one
7873 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7874 if(p->camera_entity == t->camera_entity)
7875 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7877 if (planeindex >= r_waterstate.maxwaterplanes)
7878 return; // nothing we can do, out of planes
7880 // if this triangle does not fit any known plane rendered this frame, add one
7881 if (planeindex >= r_waterstate.numwaterplanes)
7883 // store the new plane
7884 r_waterstate.numwaterplanes++;
7886 // clear materialflags and pvs
7887 p->materialflags = 0;
7888 p->pvsvalid = false;
7889 p->camera_entity = t->camera_entity;
7890 VectorCopy(surface->mins, p->mins);
7891 VectorCopy(surface->maxs, p->maxs);
7896 p->mins[0] = min(p->mins[0], surface->mins[0]);
7897 p->mins[1] = min(p->mins[1], surface->mins[1]);
7898 p->mins[2] = min(p->mins[2], surface->mins[2]);
7899 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
7900 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
7901 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
7903 // merge this surface's materialflags into the waterplane
7904 p->materialflags |= t->currentmaterialflags;
7905 if(!(p->materialflags & MATERIALFLAG_CAMERA))
7907 // merge this surface's PVS into the waterplane
7908 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7909 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7910 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7912 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7918 static void R_Water_ProcessPlanes(void)
7921 r_refdef_view_t originalview;
7922 r_refdef_view_t myview;
7924 r_waterstate_waterplane_t *p;
7927 originalview = r_refdef.view;
7929 // make sure enough textures are allocated
7930 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7932 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7934 if (!p->texture_refraction)
7935 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, -1, NULL);
7936 if (!p->texture_refraction)
7939 else if (p->materialflags & MATERIALFLAG_CAMERA)
7941 if (!p->texture_camera)
7942 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, -1, NULL);
7943 if (!p->texture_camera)
7947 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7949 if (!p->texture_reflection)
7950 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, -1, NULL);
7951 if (!p->texture_reflection)
7957 r_refdef.view = originalview;
7958 r_refdef.view.showdebug = false;
7959 r_refdef.view.width = r_waterstate.waterwidth;
7960 r_refdef.view.height = r_waterstate.waterheight;
7961 r_refdef.view.useclipplane = true;
7962 myview = r_refdef.view;
7963 r_waterstate.renderingscene = true;
7964 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7966 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7968 r_refdef.view = myview;
7969 if(r_water_scissormode.integer)
7972 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
7973 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
7976 // render reflected scene and copy into texture
7977 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7978 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7979 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7980 r_refdef.view.clipplane = p->plane;
7982 // reverse the cullface settings for this render
7983 r_refdef.view.cullface_front = GL_FRONT;
7984 r_refdef.view.cullface_back = GL_BACK;
7985 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7987 r_refdef.view.usecustompvs = true;
7989 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7991 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7994 R_ResetViewRendering3D();
7995 R_ClearScreen(r_refdef.fogenabled);
7996 if(r_water_scissormode.integer & 2)
7997 R_View_UpdateWithScissor(myscissor);
8000 if(r_water_scissormode.integer & 1)
8001 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8004 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);
8007 // render the normal view scene and copy into texture
8008 // (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)
8009 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8011 r_refdef.view = myview;
8012 if(r_water_scissormode.integer)
8015 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8016 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8019 r_waterstate.renderingrefraction = true;
8021 r_refdef.view.clipplane = p->plane;
8022 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8023 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8025 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8027 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8028 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8029 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8030 R_RenderView_UpdateViewVectors();
8031 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8033 r_refdef.view.usecustompvs = true;
8034 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);
8038 PlaneClassify(&r_refdef.view.clipplane);
8040 R_ResetViewRendering3D();
8041 R_ClearScreen(r_refdef.fogenabled);
8042 if(r_water_scissormode.integer & 2)
8043 R_View_UpdateWithScissor(myscissor);
8046 if(r_water_scissormode.integer & 1)
8047 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8050 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);
8051 r_waterstate.renderingrefraction = false;
8053 else if (p->materialflags & MATERIALFLAG_CAMERA)
8055 r_refdef.view = myview;
8057 r_refdef.view.clipplane = p->plane;
8058 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8059 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8061 r_refdef.view.width = r_waterstate.camerawidth;
8062 r_refdef.view.height = r_waterstate.cameraheight;
8063 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8064 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8066 if(p->camera_entity)
8068 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8069 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8072 // note: all of the view is used for displaying... so
8073 // there is no use in scissoring
8075 // reverse the cullface settings for this render
8076 r_refdef.view.cullface_front = GL_FRONT;
8077 r_refdef.view.cullface_back = GL_BACK;
8078 // also reverse the view matrix
8079 Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
8080 R_RenderView_UpdateViewVectors();
8081 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8083 r_refdef.view.usecustompvs = true;
8084 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);
8087 // camera needs no clipplane
8088 r_refdef.view.useclipplane = false;
8090 PlaneClassify(&r_refdef.view.clipplane);
8092 R_ResetViewRendering3D();
8093 R_ClearScreen(r_refdef.fogenabled);
8097 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);
8098 r_waterstate.renderingrefraction = false;
8102 r_waterstate.renderingscene = false;
8103 r_refdef.view = originalview;
8104 R_ResetViewRendering3D();
8105 R_ClearScreen(r_refdef.fogenabled);
8109 r_refdef.view = originalview;
8110 r_waterstate.renderingscene = false;
8111 Cvar_SetValueQuick(&r_water, 0);
8112 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8116 void R_Bloom_StartFrame(void)
8118 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8120 switch(vid.renderpath)
8122 case RENDERPATH_GL20:
8123 case RENDERPATH_CGGL:
8125 case RENDERPATH_GL13:
8126 case RENDERPATH_GL11:
8130 // set bloomwidth and bloomheight to the bloom resolution that will be
8131 // used (often less than the screen resolution for faster rendering)
8132 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8133 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8134 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8135 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8136 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8138 // calculate desired texture sizes
8139 if (vid.support.arb_texture_non_power_of_two)
8141 screentexturewidth = r_refdef.view.width;
8142 screentextureheight = r_refdef.view.height;
8143 bloomtexturewidth = r_bloomstate.bloomwidth;
8144 bloomtextureheight = r_bloomstate.bloomheight;
8148 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8149 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8150 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8151 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8154 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))
8156 Cvar_SetValueQuick(&r_hdr, 0);
8157 Cvar_SetValueQuick(&r_bloom, 0);
8158 Cvar_SetValueQuick(&r_motionblur, 0);
8159 Cvar_SetValueQuick(&r_damageblur, 0);
8162 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)))
8163 screentexturewidth = screentextureheight = 0;
8164 if (!r_hdr.integer && !r_bloom.integer)
8165 bloomtexturewidth = bloomtextureheight = 0;
8167 // allocate textures as needed
8168 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8170 if (r_bloomstate.texture_screen)
8171 R_FreeTexture(r_bloomstate.texture_screen);
8172 r_bloomstate.texture_screen = NULL;
8173 r_bloomstate.screentexturewidth = screentexturewidth;
8174 r_bloomstate.screentextureheight = screentextureheight;
8175 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8176 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
8178 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8180 if (r_bloomstate.texture_bloom)
8181 R_FreeTexture(r_bloomstate.texture_bloom);
8182 r_bloomstate.texture_bloom = NULL;
8183 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8184 r_bloomstate.bloomtextureheight = bloomtextureheight;
8185 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8186 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8189 // when doing a reduced render (HDR) we want to use a smaller area
8190 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8191 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8192 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8193 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8194 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8196 // set up a texcoord array for the full resolution screen image
8197 // (we have to keep this around to copy back during final render)
8198 r_bloomstate.screentexcoord2f[0] = 0;
8199 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8200 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8201 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8202 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8203 r_bloomstate.screentexcoord2f[5] = 0;
8204 r_bloomstate.screentexcoord2f[6] = 0;
8205 r_bloomstate.screentexcoord2f[7] = 0;
8207 // set up a texcoord array for the reduced resolution bloom image
8208 // (which will be additive blended over the screen image)
8209 r_bloomstate.bloomtexcoord2f[0] = 0;
8210 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8211 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8212 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8213 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8214 r_bloomstate.bloomtexcoord2f[5] = 0;
8215 r_bloomstate.bloomtexcoord2f[6] = 0;
8216 r_bloomstate.bloomtexcoord2f[7] = 0;
8218 if (r_hdr.integer || r_bloom.integer)
8220 r_bloomstate.enabled = true;
8221 r_bloomstate.hdr = r_hdr.integer != 0;
8224 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);
8227 void R_Bloom_CopyBloomTexture(float colorscale)
8229 r_refdef.stats.bloom++;
8231 // scale down screen texture to the bloom texture size
8233 R_SetViewport(&r_bloomstate.viewport);
8234 GL_BlendFunc(GL_ONE, GL_ZERO);
8235 GL_Color(colorscale, colorscale, colorscale, 1);
8236 // TODO: optimize with multitexture or GLSL
8237 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8238 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8239 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8240 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8242 // we now have a bloom image in the framebuffer
8243 // copy it into the bloom image texture for later processing
8244 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);
8245 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8248 void R_Bloom_CopyHDRTexture(void)
8250 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);
8251 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8254 void R_Bloom_MakeTexture(void)
8257 float xoffset, yoffset, r, brighten;
8259 r_refdef.stats.bloom++;
8261 R_ResetViewRendering2D();
8262 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8263 R_Mesh_ColorPointer(NULL, 0, 0);
8265 // we have a bloom image in the framebuffer
8267 R_SetViewport(&r_bloomstate.viewport);
8269 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8272 r = bound(0, r_bloom_colorexponent.value / x, 1);
8273 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8274 GL_Color(r, r, r, 1);
8275 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8276 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8277 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8278 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8280 // copy the vertically blurred bloom view to a texture
8281 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);
8282 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8285 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8286 brighten = r_bloom_brighten.value;
8288 brighten *= r_hdr_range.value;
8289 brighten = sqrt(brighten);
8291 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8292 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8293 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
8295 for (dir = 0;dir < 2;dir++)
8297 // blend on at multiple vertical offsets to achieve a vertical blur
8298 // TODO: do offset blends using GLSL
8299 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8300 GL_BlendFunc(GL_ONE, GL_ZERO);
8301 for (x = -range;x <= range;x++)
8303 if (!dir){xoffset = 0;yoffset = x;}
8304 else {xoffset = x;yoffset = 0;}
8305 xoffset /= (float)r_bloomstate.bloomtexturewidth;
8306 yoffset /= (float)r_bloomstate.bloomtextureheight;
8307 // compute a texcoord array with the specified x and y offset
8308 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8309 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8310 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8311 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8312 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8313 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8314 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8315 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8316 // this r value looks like a 'dot' particle, fading sharply to
8317 // black at the edges
8318 // (probably not realistic but looks good enough)
8319 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8320 //r = brighten/(range*2+1);
8321 r = brighten / (range * 2 + 1);
8323 r *= (1 - x*x/(float)(range*range));
8324 GL_Color(r, r, r, 1);
8325 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8326 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8327 GL_BlendFunc(GL_ONE, GL_ONE);
8330 // copy the vertically blurred bloom view to a texture
8331 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);
8332 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8335 // apply subtract last
8336 // (just like it would be in a GLSL shader)
8337 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
8339 GL_BlendFunc(GL_ONE, GL_ZERO);
8340 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8341 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8342 GL_Color(1, 1, 1, 1);
8343 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8344 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8346 GL_BlendFunc(GL_ONE, GL_ONE);
8347 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
8348 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8349 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8350 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
8351 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8352 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8353 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
8355 // copy the darkened bloom view to a texture
8356 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);
8357 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8361 void R_HDR_RenderBloomTexture(void)
8363 int oldwidth, oldheight;
8364 float oldcolorscale;
8366 oldcolorscale = r_refdef.view.colorscale;
8367 oldwidth = r_refdef.view.width;
8368 oldheight = r_refdef.view.height;
8369 r_refdef.view.width = r_bloomstate.bloomwidth;
8370 r_refdef.view.height = r_bloomstate.bloomheight;
8372 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
8373 // TODO: add exposure compensation features
8374 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8376 r_refdef.view.showdebug = false;
8377 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8379 R_ResetViewRendering3D();
8381 R_ClearScreen(r_refdef.fogenabled);
8382 if (r_timereport_active)
8383 R_TimeReport("HDRclear");
8386 if (r_timereport_active)
8387 R_TimeReport("visibility");
8389 // only do secondary renders with HDR if r_hdr is 2 or higher
8390 r_waterstate.numwaterplanes = 0;
8391 if (r_waterstate.enabled && r_hdr.integer >= 2)
8392 R_RenderWaterPlanes();
8394 r_refdef.view.showdebug = true;
8396 r_waterstate.numwaterplanes = 0;
8398 R_ResetViewRendering2D();
8400 R_Bloom_CopyHDRTexture();
8401 R_Bloom_MakeTexture();
8403 // restore the view settings
8404 r_refdef.view.width = oldwidth;
8405 r_refdef.view.height = oldheight;
8406 r_refdef.view.colorscale = oldcolorscale;
8408 R_ResetViewRendering3D();
8410 R_ClearScreen(r_refdef.fogenabled);
8411 if (r_timereport_active)
8412 R_TimeReport("viewclear");
8415 static void R_BlendView(void)
8417 unsigned int permutation;
8418 float uservecs[4][4];
8420 switch (vid.renderpath)
8422 case RENDERPATH_GL20:
8423 case RENDERPATH_CGGL:
8425 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8426 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8427 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8428 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8429 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8431 if (r_bloomstate.texture_screen)
8433 // make sure the buffer is available
8434 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8436 R_ResetViewRendering2D();
8437 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8438 R_Mesh_ColorPointer(NULL, 0, 0);
8440 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8442 // declare variables
8444 static float avgspeed;
8446 speed = VectorLength(cl.movement_velocity);
8448 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8449 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8451 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8452 speed = bound(0, speed, 1);
8453 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8455 // calculate values into a standard alpha
8456 cl.motionbluralpha = 1 - exp(-
8458 (r_motionblur.value * speed / 80)
8460 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8463 max(0.0001, cl.time - cl.oldtime) // fps independent
8466 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8467 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8469 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8471 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8472 GL_Color(1, 1, 1, cl.motionbluralpha);
8473 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8474 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8475 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8476 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8480 // copy view into the screen texture
8481 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);
8482 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8484 else if (!r_bloomstate.texture_bloom)
8486 // we may still have to do view tint...
8487 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8489 // apply a color tint to the whole view
8490 R_ResetViewRendering2D();
8491 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8492 R_Mesh_ColorPointer(NULL, 0, 0);
8493 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8494 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8495 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8496 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8498 break; // no screen processing, no bloom, skip it
8501 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8503 // render simple bloom effect
8504 // copy the screen and shrink it and darken it for the bloom process
8505 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8506 // make the bloom texture
8507 R_Bloom_MakeTexture();
8510 #if _MSC_VER >= 1400
8511 #define sscanf sscanf_s
8513 memset(uservecs, 0, sizeof(uservecs));
8514 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8515 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8516 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8517 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8519 R_ResetViewRendering2D();
8520 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8521 R_Mesh_ColorPointer(NULL, 0, 0);
8522 GL_Color(1, 1, 1, 1);
8523 GL_BlendFunc(GL_ONE, GL_ZERO);
8524 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8525 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8527 switch(vid.renderpath)
8529 case RENDERPATH_GL20:
8530 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8531 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8532 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8533 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8534 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]);
8535 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8536 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]);
8537 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]);
8538 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]);
8539 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]);
8540 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
8541 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8543 case RENDERPATH_CGGL:
8545 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
8546 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
8547 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
8548 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
8549 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
8550 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
8551 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
8552 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
8553 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
8554 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
8555 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
8556 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
8562 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8563 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8565 case RENDERPATH_GL13:
8566 case RENDERPATH_GL11:
8567 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8569 // apply a color tint to the whole view
8570 R_ResetViewRendering2D();
8571 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8572 R_Mesh_ColorPointer(NULL, 0, 0);
8573 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8574 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8575 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8576 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8582 matrix4x4_t r_waterscrollmatrix;
8584 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8586 if (r_refdef.fog_density)
8588 r_refdef.fogcolor[0] = r_refdef.fog_red;
8589 r_refdef.fogcolor[1] = r_refdef.fog_green;
8590 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8592 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8593 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8594 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8595 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8599 VectorCopy(r_refdef.fogcolor, fogvec);
8600 // color.rgb *= ContrastBoost * SceneBrightness;
8601 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8602 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8603 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8604 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8609 void R_UpdateVariables(void)
8613 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8615 r_refdef.farclip = r_farclip_base.value;
8616 if (r_refdef.scene.worldmodel)
8617 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8618 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8620 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8621 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8622 r_refdef.polygonfactor = 0;
8623 r_refdef.polygonoffset = 0;
8624 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8625 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8627 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8628 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8629 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8630 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8631 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8632 if (FAKELIGHT_ENABLED)
8634 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
8636 if (r_showsurfaces.integer)
8638 r_refdef.scene.rtworld = false;
8639 r_refdef.scene.rtworldshadows = false;
8640 r_refdef.scene.rtdlight = false;
8641 r_refdef.scene.rtdlightshadows = false;
8642 r_refdef.lightmapintensity = 0;
8645 if (gamemode == GAME_NEHAHRA)
8647 if (gl_fogenable.integer)
8649 r_refdef.oldgl_fogenable = true;
8650 r_refdef.fog_density = gl_fogdensity.value;
8651 r_refdef.fog_red = gl_fogred.value;
8652 r_refdef.fog_green = gl_foggreen.value;
8653 r_refdef.fog_blue = gl_fogblue.value;
8654 r_refdef.fog_alpha = 1;
8655 r_refdef.fog_start = 0;
8656 r_refdef.fog_end = gl_skyclip.value;
8657 r_refdef.fog_height = 1<<30;
8658 r_refdef.fog_fadedepth = 128;
8660 else if (r_refdef.oldgl_fogenable)
8662 r_refdef.oldgl_fogenable = false;
8663 r_refdef.fog_density = 0;
8664 r_refdef.fog_red = 0;
8665 r_refdef.fog_green = 0;
8666 r_refdef.fog_blue = 0;
8667 r_refdef.fog_alpha = 0;
8668 r_refdef.fog_start = 0;
8669 r_refdef.fog_end = 0;
8670 r_refdef.fog_height = 1<<30;
8671 r_refdef.fog_fadedepth = 128;
8675 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8676 r_refdef.fog_start = max(0, r_refdef.fog_start);
8677 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8679 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8681 if (r_refdef.fog_density && r_drawfog.integer)
8683 r_refdef.fogenabled = true;
8684 // this is the point where the fog reaches 0.9986 alpha, which we
8685 // consider a good enough cutoff point for the texture
8686 // (0.9986 * 256 == 255.6)
8687 if (r_fog_exp2.integer)
8688 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8690 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8691 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8692 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8693 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8694 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
8695 R_BuildFogHeightTexture();
8696 // fog color was already set
8697 // update the fog texture
8698 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)
8699 R_BuildFogTexture();
8700 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
8701 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
8704 r_refdef.fogenabled = false;
8706 switch(vid.renderpath)
8708 case RENDERPATH_GL20:
8709 case RENDERPATH_CGGL:
8710 if(v_glslgamma.integer && !vid_gammatables_trivial)
8712 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8714 // build GLSL gamma texture
8715 #define RAMPWIDTH 256
8716 unsigned short ramp[RAMPWIDTH * 3];
8717 unsigned char rampbgr[RAMPWIDTH][4];
8720 r_texture_gammaramps_serial = vid_gammatables_serial;
8722 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8723 for(i = 0; i < RAMPWIDTH; ++i)
8725 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8726 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8727 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8730 if (r_texture_gammaramps)
8732 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8736 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
8742 // remove GLSL gamma texture
8745 case RENDERPATH_GL13:
8746 case RENDERPATH_GL11:
8751 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8752 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8758 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8759 if( scenetype != r_currentscenetype ) {
8760 // store the old scenetype
8761 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8762 r_currentscenetype = scenetype;
8763 // move in the new scene
8764 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8773 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8775 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8776 if( scenetype == r_currentscenetype ) {
8777 return &r_refdef.scene;
8779 return &r_scenes_store[ scenetype ];
8788 void R_RenderView(void)
8790 if (r_timereport_active)
8791 R_TimeReport("start");
8792 r_textureframe++; // used only by R_GetCurrentTexture
8793 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8795 if(R_CompileShader_CheckStaticParms())
8798 if (!r_drawentities.integer)
8799 r_refdef.scene.numentities = 0;
8801 R_AnimCache_ClearCache();
8802 R_FrameData_NewFrame();
8804 if (r_refdef.view.isoverlay)
8806 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8807 GL_Clear( GL_DEPTH_BUFFER_BIT );
8808 R_TimeReport("depthclear");
8810 r_refdef.view.showdebug = false;
8812 r_waterstate.enabled = false;
8813 r_waterstate.numwaterplanes = 0;
8821 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
8822 return; //Host_Error ("R_RenderView: NULL worldmodel");
8824 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8826 R_RenderView_UpdateViewVectors();
8828 R_Shadow_UpdateWorldLightSelection();
8830 R_Bloom_StartFrame();
8831 R_Water_StartFrame();
8834 if (r_timereport_active)
8835 R_TimeReport("viewsetup");
8837 R_ResetViewRendering3D();
8839 if (r_refdef.view.clear || r_refdef.fogenabled)
8841 R_ClearScreen(r_refdef.fogenabled);
8842 if (r_timereport_active)
8843 R_TimeReport("viewclear");
8845 r_refdef.view.clear = true;
8847 // this produces a bloom texture to be used in R_BlendView() later
8848 if (r_hdr.integer && r_bloomstate.bloomwidth)
8850 R_HDR_RenderBloomTexture();
8851 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8852 r_textureframe++; // used only by R_GetCurrentTexture
8855 r_refdef.view.showdebug = true;
8858 if (r_timereport_active)
8859 R_TimeReport("visibility");
8861 r_waterstate.numwaterplanes = 0;
8862 if (r_waterstate.enabled)
8863 R_RenderWaterPlanes();
8866 r_waterstate.numwaterplanes = 0;
8869 if (r_timereport_active)
8870 R_TimeReport("blendview");
8872 GL_Scissor(0, 0, vid.width, vid.height);
8873 GL_ScissorTest(false);
8878 void R_RenderWaterPlanes(void)
8880 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8882 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8883 if (r_timereport_active)
8884 R_TimeReport("waterworld");
8887 // don't let sound skip if going slow
8888 if (r_refdef.scene.extraupdate)
8891 R_DrawModelsAddWaterPlanes();
8892 if (r_timereport_active)
8893 R_TimeReport("watermodels");
8895 if (r_waterstate.numwaterplanes)
8897 R_Water_ProcessPlanes();
8898 if (r_timereport_active)
8899 R_TimeReport("waterscenes");
8903 extern void R_DrawLightningBeams (void);
8904 extern void VM_CL_AddPolygonsToMeshQueue (void);
8905 extern void R_DrawPortals (void);
8906 extern cvar_t cl_locs_show;
8907 static void R_DrawLocs(void);
8908 static void R_DrawEntityBBoxes(void);
8909 static void R_DrawModelDecals(void);
8910 extern void R_DrawModelShadows(void);
8911 extern void R_DrawModelShadowMaps(void);
8912 extern cvar_t cl_decals_newsystem;
8913 extern qboolean r_shadow_usingdeferredprepass;
8914 void R_RenderScene(void)
8916 qboolean shadowmapping = false;
8918 if (r_timereport_active)
8919 R_TimeReport("beginscene");
8921 r_refdef.stats.renders++;
8925 // don't let sound skip if going slow
8926 if (r_refdef.scene.extraupdate)
8929 R_MeshQueue_BeginScene();
8933 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);
8935 if (r_timereport_active)
8936 R_TimeReport("skystartframe");
8938 if (cl.csqc_vidvars.drawworld)
8940 // don't let sound skip if going slow
8941 if (r_refdef.scene.extraupdate)
8944 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8946 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8947 if (r_timereport_active)
8948 R_TimeReport("worldsky");
8951 if (R_DrawBrushModelsSky() && r_timereport_active)
8952 R_TimeReport("bmodelsky");
8954 if (skyrendermasked && skyrenderlater)
8956 // we have to force off the water clipping plane while rendering sky
8960 if (r_timereport_active)
8961 R_TimeReport("sky");
8965 R_AnimCache_CacheVisibleEntities();
8966 if (r_timereport_active)
8967 R_TimeReport("animation");
8969 R_Shadow_PrepareLights();
8970 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8971 R_Shadow_PrepareModelShadows();
8972 if (r_timereport_active)
8973 R_TimeReport("preparelights");
8975 if (R_Shadow_ShadowMappingEnabled())
8976 shadowmapping = true;
8978 if (r_shadow_usingdeferredprepass)
8979 R_Shadow_DrawPrepass();
8981 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8983 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8984 if (r_timereport_active)
8985 R_TimeReport("worlddepth");
8987 if (r_depthfirst.integer >= 2)
8989 R_DrawModelsDepth();
8990 if (r_timereport_active)
8991 R_TimeReport("modeldepth");
8994 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
8996 R_DrawModelShadowMaps();
8997 R_ResetViewRendering3D();
8998 // don't let sound skip if going slow
8999 if (r_refdef.scene.extraupdate)
9003 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9005 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9006 if (r_timereport_active)
9007 R_TimeReport("world");
9010 // don't let sound skip if going slow
9011 if (r_refdef.scene.extraupdate)
9015 if (r_timereport_active)
9016 R_TimeReport("models");
9018 // don't let sound skip if going slow
9019 if (r_refdef.scene.extraupdate)
9022 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9024 R_DrawModelShadows();
9025 R_ResetViewRendering3D();
9026 // don't let sound skip if going slow
9027 if (r_refdef.scene.extraupdate)
9031 if (!r_shadow_usingdeferredprepass)
9033 R_Shadow_DrawLights();
9034 if (r_timereport_active)
9035 R_TimeReport("rtlights");
9038 // don't let sound skip if going slow
9039 if (r_refdef.scene.extraupdate)
9042 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9044 R_DrawModelShadows();
9045 R_ResetViewRendering3D();
9046 // don't let sound skip if going slow
9047 if (r_refdef.scene.extraupdate)
9051 if (cl.csqc_vidvars.drawworld)
9053 if (cl_decals_newsystem.integer)
9055 R_DrawModelDecals();
9056 if (r_timereport_active)
9057 R_TimeReport("modeldecals");
9062 if (r_timereport_active)
9063 R_TimeReport("decals");
9067 if (r_timereport_active)
9068 R_TimeReport("particles");
9071 if (r_timereport_active)
9072 R_TimeReport("explosions");
9074 R_DrawLightningBeams();
9075 if (r_timereport_active)
9076 R_TimeReport("lightning");
9079 VM_CL_AddPolygonsToMeshQueue();
9081 if (r_refdef.view.showdebug)
9083 if (cl_locs_show.integer)
9086 if (r_timereport_active)
9087 R_TimeReport("showlocs");
9090 if (r_drawportals.integer)
9093 if (r_timereport_active)
9094 R_TimeReport("portals");
9097 if (r_showbboxes.value > 0)
9099 R_DrawEntityBBoxes();
9100 if (r_timereport_active)
9101 R_TimeReport("bboxes");
9105 R_MeshQueue_RenderTransparent();
9106 if (r_timereport_active)
9107 R_TimeReport("drawtrans");
9109 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))
9111 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9112 if (r_timereport_active)
9113 R_TimeReport("worlddebug");
9114 R_DrawModelsDebug();
9115 if (r_timereport_active)
9116 R_TimeReport("modeldebug");
9119 if (cl.csqc_vidvars.drawworld)
9121 R_Shadow_DrawCoronas();
9122 if (r_timereport_active)
9123 R_TimeReport("coronas");
9128 GL_DepthTest(false);
9129 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9130 GL_Color(1, 1, 1, 1);
9131 qglBegin(GL_POLYGON);
9132 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9133 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9134 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9135 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9137 qglBegin(GL_POLYGON);
9138 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
9139 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
9140 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
9141 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
9143 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9147 // don't let sound skip if going slow
9148 if (r_refdef.scene.extraupdate)
9151 R_ResetViewRendering2D();
9154 static const unsigned short bboxelements[36] =
9164 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9167 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9169 RSurf_ActiveWorldEntity();
9171 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9172 GL_DepthMask(false);
9173 GL_DepthRange(0, 1);
9174 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9175 R_Mesh_ResetTextureState();
9177 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9178 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9179 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9180 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9181 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9182 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9183 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9184 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9185 R_FillColors(color4f, 8, cr, cg, cb, ca);
9186 if (r_refdef.fogenabled)
9188 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9190 f1 = RSurf_FogVertex(v);
9192 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9193 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9194 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9197 R_Mesh_VertexPointer(vertex3f, 0, 0);
9198 R_Mesh_ColorPointer(color4f, 0, 0);
9199 R_Mesh_ResetTextureState();
9200 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9201 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
9204 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9208 prvm_edict_t *edict;
9209 prvm_prog_t *prog_save = prog;
9211 // this function draws bounding boxes of server entities
9215 GL_CullFace(GL_NONE);
9216 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9220 for (i = 0;i < numsurfaces;i++)
9222 edict = PRVM_EDICT_NUM(surfacelist[i]);
9223 switch ((int)edict->fields.server->solid)
9225 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9226 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9227 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9228 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9229 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9230 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9232 color[3] *= r_showbboxes.value;
9233 color[3] = bound(0, color[3], 1);
9234 GL_DepthTest(!r_showdisabledepthtest.integer);
9235 GL_CullFace(r_refdef.view.cullface_front);
9236 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9242 static void R_DrawEntityBBoxes(void)
9245 prvm_edict_t *edict;
9247 prvm_prog_t *prog_save = prog;
9249 // this function draws bounding boxes of server entities
9255 for (i = 0;i < prog->num_edicts;i++)
9257 edict = PRVM_EDICT_NUM(i);
9258 if (edict->priv.server->free)
9260 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9261 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9263 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9265 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9266 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9272 static const int nomodelelement3i[24] =
9284 static const unsigned short nomodelelement3s[24] =
9296 static const float nomodelvertex3f[6*3] =
9306 static const float nomodelcolor4f[6*4] =
9308 0.0f, 0.0f, 0.5f, 1.0f,
9309 0.0f, 0.0f, 0.5f, 1.0f,
9310 0.0f, 0.5f, 0.0f, 1.0f,
9311 0.0f, 0.5f, 0.0f, 1.0f,
9312 0.5f, 0.0f, 0.0f, 1.0f,
9313 0.5f, 0.0f, 0.0f, 1.0f
9316 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9322 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);
9324 // this is only called once per entity so numsurfaces is always 1, and
9325 // surfacelist is always {0}, so this code does not handle batches
9327 if (rsurface.ent_flags & RENDER_ADDITIVE)
9329 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9330 GL_DepthMask(false);
9332 else if (rsurface.colormod[3] < 1)
9334 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9335 GL_DepthMask(false);
9339 GL_BlendFunc(GL_ONE, GL_ZERO);
9342 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9343 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9344 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9345 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9346 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9347 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9348 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9349 R_Mesh_ColorPointer(color4f, 0, 0);
9350 for (i = 0, c = color4f;i < 6;i++, c += 4)
9352 c[0] *= rsurface.colormod[0];
9353 c[1] *= rsurface.colormod[1];
9354 c[2] *= rsurface.colormod[2];
9355 c[3] *= rsurface.colormod[3];
9357 if (r_refdef.fogenabled)
9359 for (i = 0, c = color4f;i < 6;i++, c += 4)
9361 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
9363 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9364 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9365 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9368 R_Mesh_ResetTextureState();
9369 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
9372 void R_DrawNoModel(entity_render_t *ent)
9375 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9376 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9377 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9379 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9382 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9384 vec3_t right1, right2, diff, normal;
9386 VectorSubtract (org2, org1, normal);
9388 // calculate 'right' vector for start
9389 VectorSubtract (r_refdef.view.origin, org1, diff);
9390 CrossProduct (normal, diff, right1);
9391 VectorNormalize (right1);
9393 // calculate 'right' vector for end
9394 VectorSubtract (r_refdef.view.origin, org2, diff);
9395 CrossProduct (normal, diff, right2);
9396 VectorNormalize (right2);
9398 vert[ 0] = org1[0] + width * right1[0];
9399 vert[ 1] = org1[1] + width * right1[1];
9400 vert[ 2] = org1[2] + width * right1[2];
9401 vert[ 3] = org1[0] - width * right1[0];
9402 vert[ 4] = org1[1] - width * right1[1];
9403 vert[ 5] = org1[2] - width * right1[2];
9404 vert[ 6] = org2[0] - width * right2[0];
9405 vert[ 7] = org2[1] - width * right2[1];
9406 vert[ 8] = org2[2] - width * right2[2];
9407 vert[ 9] = org2[0] + width * right2[0];
9408 vert[10] = org2[1] + width * right2[1];
9409 vert[11] = org2[2] + width * right2[2];
9412 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)
9414 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9415 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9416 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9417 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9418 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9419 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9420 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9421 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9422 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9423 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9424 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9425 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9428 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9433 VectorSet(v, x, y, z);
9434 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9435 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9437 if (i == mesh->numvertices)
9439 if (mesh->numvertices < mesh->maxvertices)
9441 VectorCopy(v, vertex3f);
9442 mesh->numvertices++;
9444 return mesh->numvertices;
9450 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9454 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9455 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9456 e = mesh->element3i + mesh->numtriangles * 3;
9457 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9459 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9460 if (mesh->numtriangles < mesh->maxtriangles)
9465 mesh->numtriangles++;
9467 element[1] = element[2];
9471 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9475 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9476 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9477 e = mesh->element3i + mesh->numtriangles * 3;
9478 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9480 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9481 if (mesh->numtriangles < mesh->maxtriangles)
9486 mesh->numtriangles++;
9488 element[1] = element[2];
9492 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9493 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9495 int planenum, planenum2;
9498 mplane_t *plane, *plane2;
9500 double temppoints[2][256*3];
9501 // figure out how large a bounding box we need to properly compute this brush
9503 for (w = 0;w < numplanes;w++)
9504 maxdist = max(maxdist, fabs(planes[w].dist));
9505 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9506 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9507 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9511 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9512 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9514 if (planenum2 == planenum)
9516 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);
9519 if (tempnumpoints < 3)
9521 // generate elements forming a triangle fan for this polygon
9522 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9526 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)
9528 texturelayer_t *layer;
9529 layer = t->currentlayers + t->currentnumlayers++;
9531 layer->depthmask = depthmask;
9532 layer->blendfunc1 = blendfunc1;
9533 layer->blendfunc2 = blendfunc2;
9534 layer->texture = texture;
9535 layer->texmatrix = *matrix;
9536 layer->color[0] = r;
9537 layer->color[1] = g;
9538 layer->color[2] = b;
9539 layer->color[3] = a;
9542 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9544 if(parms[0] == 0 && parms[1] == 0)
9546 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9547 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9552 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9555 index = parms[2] + r_refdef.scene.time * parms[3];
9556 index -= floor(index);
9557 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9560 case Q3WAVEFUNC_NONE:
9561 case Q3WAVEFUNC_NOISE:
9562 case Q3WAVEFUNC_COUNT:
9565 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9566 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9567 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9568 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9569 case Q3WAVEFUNC_TRIANGLE:
9571 f = index - floor(index);
9582 f = parms[0] + parms[1] * f;
9583 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9584 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9588 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9593 matrix4x4_t matrix, temp;
9594 switch(tcmod->tcmod)
9598 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9599 matrix = r_waterscrollmatrix;
9601 matrix = identitymatrix;
9603 case Q3TCMOD_ENTITYTRANSLATE:
9604 // this is used in Q3 to allow the gamecode to control texcoord
9605 // scrolling on the entity, which is not supported in darkplaces yet.
9606 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9608 case Q3TCMOD_ROTATE:
9609 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9610 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9611 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9614 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9616 case Q3TCMOD_SCROLL:
9617 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9619 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9620 w = (int) tcmod->parms[0];
9621 h = (int) tcmod->parms[1];
9622 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9624 idx = (int) floor(f * w * h);
9625 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9627 case Q3TCMOD_STRETCH:
9628 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9629 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9631 case Q3TCMOD_TRANSFORM:
9632 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
9633 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
9634 VectorSet(tcmat + 6, 0 , 0 , 1);
9635 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
9636 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9638 case Q3TCMOD_TURBULENT:
9639 // this is handled in the RSurf_PrepareVertices function
9640 matrix = identitymatrix;
9644 Matrix4x4_Concat(texmatrix, &matrix, &temp);
9647 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9649 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9650 char name[MAX_QPATH];
9651 skinframe_t *skinframe;
9652 unsigned char pixels[296*194];
9653 strlcpy(cache->name, skinname, sizeof(cache->name));
9654 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9655 if (developer_loading.integer)
9656 Con_Printf("loading %s\n", name);
9657 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9658 if (!skinframe || !skinframe->base)
9661 fs_offset_t filesize;
9663 f = FS_LoadFile(name, tempmempool, true, &filesize);
9666 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9667 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9671 cache->skinframe = skinframe;
9674 texture_t *R_GetCurrentTexture(texture_t *t)
9677 const entity_render_t *ent = rsurface.entity;
9678 dp_model_t *model = ent->model;
9679 q3shaderinfo_layer_tcmod_t *tcmod;
9681 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9682 return t->currentframe;
9683 t->update_lastrenderframe = r_textureframe;
9684 t->update_lastrenderentity = (void *)ent;
9686 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
9687 t->camera_entity = ent->entitynumber;
9689 t->camera_entity = 0;
9691 // switch to an alternate material if this is a q1bsp animated material
9693 texture_t *texture = t;
9694 int s = rsurface.ent_skinnum;
9695 if ((unsigned int)s >= (unsigned int)model->numskins)
9697 if (model->skinscenes)
9699 if (model->skinscenes[s].framecount > 1)
9700 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9702 s = model->skinscenes[s].firstframe;
9705 t = t + s * model->num_surfaces;
9708 // use an alternate animation if the entity's frame is not 0,
9709 // and only if the texture has an alternate animation
9710 if (rsurface.ent_alttextures && t->anim_total[1])
9711 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9713 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9715 texture->currentframe = t;
9718 // update currentskinframe to be a qw skin or animation frame
9719 if (rsurface.ent_qwskin >= 0)
9721 i = rsurface.ent_qwskin;
9722 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9724 r_qwskincache_size = cl.maxclients;
9726 Mem_Free(r_qwskincache);
9727 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9729 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9730 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9731 t->currentskinframe = r_qwskincache[i].skinframe;
9732 if (t->currentskinframe == NULL)
9733 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9735 else if (t->numskinframes >= 2)
9736 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9737 if (t->backgroundnumskinframes >= 2)
9738 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9740 t->currentmaterialflags = t->basematerialflags;
9741 t->currentalpha = rsurface.colormod[3];
9742 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9743 t->currentalpha *= r_wateralpha.value;
9744 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9745 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
9746 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9747 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
9748 if (!(rsurface.ent_flags & RENDER_LIGHT))
9749 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9750 else if (FAKELIGHT_ENABLED)
9752 // no modellight if using fakelight for the map
9754 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9756 // pick a model lighting mode
9757 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9758 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9760 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9762 if (rsurface.ent_flags & RENDER_ADDITIVE)
9763 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9764 else if (t->currentalpha < 1)
9765 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9766 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9767 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9768 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9769 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9770 if (t->backgroundnumskinframes)
9771 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9772 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9774 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
9775 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9778 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
9779 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9780 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9782 // there is no tcmod
9783 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9785 t->currenttexmatrix = r_waterscrollmatrix;
9786 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9788 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9790 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9791 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9794 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9795 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9796 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9797 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9799 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9800 if (t->currentskinframe->qpixels)
9801 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9802 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9803 if (!t->basetexture)
9804 t->basetexture = r_texture_notexture;
9805 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9806 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9807 t->nmaptexture = t->currentskinframe->nmap;
9808 if (!t->nmaptexture)
9809 t->nmaptexture = r_texture_blanknormalmap;
9810 t->glosstexture = r_texture_black;
9811 t->glowtexture = t->currentskinframe->glow;
9812 t->fogtexture = t->currentskinframe->fog;
9813 t->reflectmasktexture = t->currentskinframe->reflect;
9814 if (t->backgroundnumskinframes)
9816 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9817 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9818 t->backgroundglosstexture = r_texture_black;
9819 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9820 if (!t->backgroundnmaptexture)
9821 t->backgroundnmaptexture = r_texture_blanknormalmap;
9825 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9826 t->backgroundnmaptexture = r_texture_blanknormalmap;
9827 t->backgroundglosstexture = r_texture_black;
9828 t->backgroundglowtexture = NULL;
9830 t->specularpower = r_shadow_glossexponent.value;
9831 // TODO: store reference values for these in the texture?
9832 t->specularscale = 0;
9833 if (r_shadow_gloss.integer > 0)
9835 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9837 if (r_shadow_glossintensity.value > 0)
9839 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9840 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9841 t->specularscale = r_shadow_glossintensity.value;
9844 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9846 t->glosstexture = r_texture_white;
9847 t->backgroundglosstexture = r_texture_white;
9848 t->specularscale = r_shadow_gloss2intensity.value;
9849 t->specularpower = r_shadow_gloss2exponent.value;
9852 t->specularscale *= t->specularscalemod;
9853 t->specularpower *= t->specularpowermod;
9855 // lightmaps mode looks bad with dlights using actual texturing, so turn
9856 // off the colormap and glossmap, but leave the normalmap on as it still
9857 // accurately represents the shading involved
9858 if (gl_lightmaps.integer)
9860 t->basetexture = r_texture_grey128;
9861 t->pantstexture = r_texture_black;
9862 t->shirttexture = r_texture_black;
9863 t->nmaptexture = r_texture_blanknormalmap;
9864 t->glosstexture = r_texture_black;
9865 t->glowtexture = NULL;
9866 t->fogtexture = NULL;
9867 t->reflectmasktexture = NULL;
9868 t->backgroundbasetexture = NULL;
9869 t->backgroundnmaptexture = r_texture_blanknormalmap;
9870 t->backgroundglosstexture = r_texture_black;
9871 t->backgroundglowtexture = NULL;
9872 t->specularscale = 0;
9873 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9876 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9877 VectorClear(t->dlightcolor);
9878 t->currentnumlayers = 0;
9879 if (t->currentmaterialflags & MATERIALFLAG_WALL)
9881 int blendfunc1, blendfunc2;
9883 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9885 blendfunc1 = GL_SRC_ALPHA;
9886 blendfunc2 = GL_ONE;
9888 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9890 blendfunc1 = GL_SRC_ALPHA;
9891 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9893 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9895 blendfunc1 = t->customblendfunc[0];
9896 blendfunc2 = t->customblendfunc[1];
9900 blendfunc1 = GL_ONE;
9901 blendfunc2 = GL_ZERO;
9903 // don't colormod evilblend textures
9904 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
9905 VectorSet(t->lightmapcolor, 1, 1, 1);
9906 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9907 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9909 // fullbright is not affected by r_refdef.lightmapintensity
9910 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]);
9911 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9912 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]);
9913 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9914 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]);
9918 vec3_t ambientcolor;
9920 // set the color tint used for lights affecting this surface
9921 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9923 // q3bsp has no lightmap updates, so the lightstylevalue that
9924 // would normally be baked into the lightmap must be
9925 // applied to the color
9926 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9927 if (model->type == mod_brushq3)
9928 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9929 colorscale *= r_refdef.lightmapintensity;
9930 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9931 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9932 // basic lit geometry
9933 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]);
9934 // add pants/shirt if needed
9935 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9936 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]);
9937 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9938 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]);
9939 // now add ambient passes if needed
9940 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9942 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]);
9943 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9944 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]);
9945 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9946 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]);
9949 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9950 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]);
9951 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9953 // if this is opaque use alpha blend which will darken the earlier
9956 // if this is an alpha blended material, all the earlier passes
9957 // were darkened by fog already, so we only need to add the fog
9958 // color ontop through the fog mask texture
9960 // if this is an additive blended material, all the earlier passes
9961 // were darkened by fog already, and we should not add fog color
9962 // (because the background was not darkened, there is no fog color
9963 // that was lost behind it).
9964 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]);
9968 return t->currentframe;
9971 rsurfacestate_t rsurface;
9973 void R_Mesh_ResizeArrays(int newvertices)
9976 if (rsurface.array_size >= newvertices)
9978 if (rsurface.array_modelvertex3f)
9979 Mem_Free(rsurface.array_modelvertex3f);
9980 rsurface.array_size = (newvertices + 1023) & ~1023;
9981 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9982 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
9983 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
9984 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
9985 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
9986 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
9987 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9988 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9989 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
9990 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
9991 rsurface.array_color4f = base + rsurface.array_size * 27;
9992 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9995 void RSurf_ActiveWorldEntity(void)
9997 dp_model_t *model = r_refdef.scene.worldmodel;
9998 //if (rsurface.entity == r_refdef.scene.worldentity)
10000 rsurface.entity = r_refdef.scene.worldentity;
10001 rsurface.skeleton = NULL;
10002 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10003 rsurface.ent_skinnum = 0;
10004 rsurface.ent_qwskin = -1;
10005 rsurface.ent_shadertime = 0;
10006 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10007 if (rsurface.array_size < model->surfmesh.num_vertices)
10008 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10009 rsurface.matrix = identitymatrix;
10010 rsurface.inversematrix = identitymatrix;
10011 rsurface.matrixscale = 1;
10012 rsurface.inversematrixscale = 1;
10013 R_EntityMatrix(&identitymatrix);
10014 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10015 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10016 rsurface.fograngerecip = r_refdef.fograngerecip;
10017 rsurface.fogheightfade = r_refdef.fogheightfade;
10018 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10019 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10020 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10021 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10022 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10023 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10024 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10025 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10026 rsurface.colormod[3] = 1;
10027 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);
10028 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10029 rsurface.frameblend[0].lerp = 1;
10030 rsurface.ent_alttextures = false;
10031 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10032 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10033 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10034 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
10035 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10036 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10037 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
10038 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10039 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10040 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
10041 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10042 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10043 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
10044 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10045 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10046 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
10047 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10048 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10049 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
10050 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10051 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10052 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
10053 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10054 rsurface.modelelement3i = model->surfmesh.data_element3i;
10055 rsurface.modelelement3s = model->surfmesh.data_element3s;
10056 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
10057 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
10058 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10059 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
10060 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
10061 rsurface.modelsurfaces = model->data_surfaces;
10062 rsurface.generatedvertex = false;
10063 rsurface.vertex3f = rsurface.modelvertex3f;
10064 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10065 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10066 rsurface.svector3f = rsurface.modelsvector3f;
10067 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10068 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10069 rsurface.tvector3f = rsurface.modeltvector3f;
10070 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10071 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10072 rsurface.normal3f = rsurface.modelnormal3f;
10073 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10074 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10075 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10078 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10080 dp_model_t *model = ent->model;
10081 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10083 rsurface.entity = (entity_render_t *)ent;
10084 rsurface.skeleton = ent->skeleton;
10085 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10086 rsurface.ent_skinnum = ent->skinnum;
10087 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;
10088 rsurface.ent_shadertime = ent->shadertime;
10089 rsurface.ent_flags = ent->flags;
10090 if (rsurface.array_size < model->surfmesh.num_vertices)
10091 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10092 rsurface.matrix = ent->matrix;
10093 rsurface.inversematrix = ent->inversematrix;
10094 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10095 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10096 R_EntityMatrix(&rsurface.matrix);
10097 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10098 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10099 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10100 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10101 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10102 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10103 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10104 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10105 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10106 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10107 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10108 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10109 rsurface.colormod[3] = ent->alpha;
10110 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10111 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10112 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10113 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10114 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10115 if (ent->model->brush.submodel && !prepass)
10117 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10118 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10120 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10122 if (ent->animcache_vertex3f && !r_framedata_failed)
10124 rsurface.modelvertex3f = ent->animcache_vertex3f;
10125 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10126 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10127 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10129 else if (wanttangents)
10131 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10132 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10133 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10134 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10135 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10137 else if (wantnormals)
10139 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10140 rsurface.modelsvector3f = NULL;
10141 rsurface.modeltvector3f = NULL;
10142 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10143 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10147 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10148 rsurface.modelsvector3f = NULL;
10149 rsurface.modeltvector3f = NULL;
10150 rsurface.modelnormal3f = NULL;
10151 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10153 rsurface.modelvertex3f_bufferobject = 0;
10154 rsurface.modelvertex3f_bufferoffset = 0;
10155 rsurface.modelsvector3f_bufferobject = 0;
10156 rsurface.modelsvector3f_bufferoffset = 0;
10157 rsurface.modeltvector3f_bufferobject = 0;
10158 rsurface.modeltvector3f_bufferoffset = 0;
10159 rsurface.modelnormal3f_bufferobject = 0;
10160 rsurface.modelnormal3f_bufferoffset = 0;
10161 rsurface.generatedvertex = true;
10165 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10166 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
10167 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10168 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10169 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
10170 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10171 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10172 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
10173 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10174 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10175 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
10176 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10177 rsurface.generatedvertex = false;
10179 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10180 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
10181 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10182 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10183 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
10184 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10185 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10186 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
10187 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10188 rsurface.modelelement3i = model->surfmesh.data_element3i;
10189 rsurface.modelelement3s = model->surfmesh.data_element3s;
10190 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
10191 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
10192 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10193 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
10194 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
10195 rsurface.modelsurfaces = model->data_surfaces;
10196 rsurface.vertex3f = rsurface.modelvertex3f;
10197 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10198 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10199 rsurface.svector3f = rsurface.modelsvector3f;
10200 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10201 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10202 rsurface.tvector3f = rsurface.modeltvector3f;
10203 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10204 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10205 rsurface.normal3f = rsurface.modelnormal3f;
10206 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10207 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10208 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10211 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)
10213 rsurface.entity = r_refdef.scene.worldentity;
10214 rsurface.skeleton = NULL;
10215 rsurface.ent_skinnum = 0;
10216 rsurface.ent_qwskin = -1;
10217 rsurface.ent_shadertime = shadertime;
10218 rsurface.ent_flags = entflags;
10219 rsurface.modelnum_vertices = numvertices;
10220 rsurface.modelnum_triangles = numtriangles;
10221 if (rsurface.array_size < rsurface.modelnum_vertices)
10222 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
10223 rsurface.matrix = *matrix;
10224 rsurface.inversematrix = *inversematrix;
10225 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10226 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10227 R_EntityMatrix(&rsurface.matrix);
10228 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10229 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10230 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10231 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10232 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10233 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10234 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10235 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10236 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10237 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10238 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10239 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10240 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);
10241 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10242 rsurface.frameblend[0].lerp = 1;
10243 rsurface.ent_alttextures = false;
10244 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10245 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10248 rsurface.modelvertex3f = vertex3f;
10249 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10250 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10251 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10253 else if (wantnormals)
10255 rsurface.modelvertex3f = vertex3f;
10256 rsurface.modelsvector3f = NULL;
10257 rsurface.modeltvector3f = NULL;
10258 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10262 rsurface.modelvertex3f = vertex3f;
10263 rsurface.modelsvector3f = NULL;
10264 rsurface.modeltvector3f = NULL;
10265 rsurface.modelnormal3f = NULL;
10267 rsurface.modelvertex3f_bufferobject = 0;
10268 rsurface.modelvertex3f_bufferoffset = 0;
10269 rsurface.modelsvector3f_bufferobject = 0;
10270 rsurface.modelsvector3f_bufferoffset = 0;
10271 rsurface.modeltvector3f_bufferobject = 0;
10272 rsurface.modeltvector3f_bufferoffset = 0;
10273 rsurface.modelnormal3f_bufferobject = 0;
10274 rsurface.modelnormal3f_bufferoffset = 0;
10275 rsurface.generatedvertex = true;
10276 rsurface.modellightmapcolor4f = color4f;
10277 rsurface.modellightmapcolor4f_bufferobject = 0;
10278 rsurface.modellightmapcolor4f_bufferoffset = 0;
10279 rsurface.modeltexcoordtexture2f = texcoord2f;
10280 rsurface.modeltexcoordtexture2f_bufferobject = 0;
10281 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10282 rsurface.modeltexcoordlightmap2f = NULL;
10283 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
10284 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10285 rsurface.modelelement3i = element3i;
10286 rsurface.modelelement3s = element3s;
10287 rsurface.modelelement3i_bufferobject = 0;
10288 rsurface.modelelement3s_bufferobject = 0;
10289 rsurface.modellightmapoffsets = NULL;
10290 rsurface.modelsurfaces = NULL;
10291 rsurface.vertex3f = rsurface.modelvertex3f;
10292 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10293 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10294 rsurface.svector3f = rsurface.modelsvector3f;
10295 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10296 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10297 rsurface.tvector3f = rsurface.modeltvector3f;
10298 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10299 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10300 rsurface.normal3f = rsurface.modelnormal3f;
10301 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10302 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10303 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10305 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
10307 if ((wantnormals || wanttangents) && !normal3f)
10308 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10309 if (wanttangents && !svector3f)
10310 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);
10314 float RSurf_FogPoint(const float *v)
10316 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10317 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10318 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10319 float FogHeightFade = r_refdef.fogheightfade;
10321 unsigned int fogmasktableindex;
10322 if (r_refdef.fogplaneviewabove)
10323 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10325 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10326 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10327 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10330 float RSurf_FogVertex(const float *v)
10332 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10333 float FogPlaneViewDist = rsurface.fogplaneviewdist;
10334 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10335 float FogHeightFade = rsurface.fogheightfade;
10337 unsigned int fogmasktableindex;
10338 if (r_refdef.fogplaneviewabove)
10339 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10341 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10342 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10343 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10346 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10347 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10350 int texturesurfaceindex;
10355 const float *v1, *in_tc;
10357 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10358 float waveparms[4];
10359 q3shaderinfo_deform_t *deform;
10360 // 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
10361 if (rsurface.generatedvertex)
10363 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
10364 generatenormals = true;
10365 for (i = 0;i < Q3MAXDEFORMS;i++)
10367 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
10369 generatetangents = true;
10370 generatenormals = true;
10372 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
10373 generatenormals = true;
10375 if (generatenormals && !rsurface.modelnormal3f)
10377 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10378 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
10379 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
10380 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10382 if (generatetangents && !rsurface.modelsvector3f)
10384 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10385 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
10386 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
10387 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10388 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
10389 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
10390 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);
10393 rsurface.vertex3f = rsurface.modelvertex3f;
10394 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10395 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10396 rsurface.svector3f = rsurface.modelsvector3f;
10397 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10398 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10399 rsurface.tvector3f = rsurface.modeltvector3f;
10400 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10401 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10402 rsurface.normal3f = rsurface.modelnormal3f;
10403 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10404 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10405 // if vertices are deformed (sprite flares and things in maps, possibly
10406 // water waves, bulges and other deformations), generate them into
10407 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
10408 // (may be static model data or generated data for an animated model, or
10409 // the previous deform pass)
10410 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10412 switch (deform->deform)
10415 case Q3DEFORM_PROJECTIONSHADOW:
10416 case Q3DEFORM_TEXT0:
10417 case Q3DEFORM_TEXT1:
10418 case Q3DEFORM_TEXT2:
10419 case Q3DEFORM_TEXT3:
10420 case Q3DEFORM_TEXT4:
10421 case Q3DEFORM_TEXT5:
10422 case Q3DEFORM_TEXT6:
10423 case Q3DEFORM_TEXT7:
10424 case Q3DEFORM_NONE:
10426 case Q3DEFORM_AUTOSPRITE:
10427 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10428 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10429 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10430 VectorNormalize(newforward);
10431 VectorNormalize(newright);
10432 VectorNormalize(newup);
10433 // make deformed versions of only the model vertices used by the specified surfaces
10434 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10436 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10437 // a single autosprite surface can contain multiple sprites...
10438 for (j = 0;j < surface->num_vertices - 3;j += 4)
10440 VectorClear(center);
10441 for (i = 0;i < 4;i++)
10442 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10443 VectorScale(center, 0.25f, center);
10444 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
10445 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
10446 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
10447 for (i = 0;i < 4;i++)
10449 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
10450 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10453 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);
10454 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);
10456 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10457 rsurface.vertex3f_bufferobject = 0;
10458 rsurface.vertex3f_bufferoffset = 0;
10459 rsurface.svector3f = rsurface.array_deformedsvector3f;
10460 rsurface.svector3f_bufferobject = 0;
10461 rsurface.svector3f_bufferoffset = 0;
10462 rsurface.tvector3f = rsurface.array_deformedtvector3f;
10463 rsurface.tvector3f_bufferobject = 0;
10464 rsurface.tvector3f_bufferoffset = 0;
10465 rsurface.normal3f = rsurface.array_deformednormal3f;
10466 rsurface.normal3f_bufferobject = 0;
10467 rsurface.normal3f_bufferoffset = 0;
10469 case Q3DEFORM_AUTOSPRITE2:
10470 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10471 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10472 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10473 VectorNormalize(newforward);
10474 VectorNormalize(newright);
10475 VectorNormalize(newup);
10476 // make deformed versions of only the model vertices used by the specified surfaces
10477 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10479 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10480 const float *v1, *v2;
10490 memset(shortest, 0, sizeof(shortest));
10491 // a single autosprite surface can contain multiple sprites...
10492 for (j = 0;j < surface->num_vertices - 3;j += 4)
10494 VectorClear(center);
10495 for (i = 0;i < 4;i++)
10496 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10497 VectorScale(center, 0.25f, center);
10498 // find the two shortest edges, then use them to define the
10499 // axis vectors for rotating around the central axis
10500 for (i = 0;i < 6;i++)
10502 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
10503 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
10505 Debug_PolygonBegin(NULL, 0);
10506 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
10507 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);
10508 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
10509 Debug_PolygonEnd();
10511 l = VectorDistance2(v1, v2);
10512 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10513 if (v1[2] != v2[2])
10514 l += (1.0f / 1024.0f);
10515 if (shortest[0].length2 > l || i == 0)
10517 shortest[1] = shortest[0];
10518 shortest[0].length2 = l;
10519 shortest[0].v1 = v1;
10520 shortest[0].v2 = v2;
10522 else if (shortest[1].length2 > l || i == 1)
10524 shortest[1].length2 = l;
10525 shortest[1].v1 = v1;
10526 shortest[1].v2 = v2;
10529 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10530 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10532 Debug_PolygonBegin(NULL, 0);
10533 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
10534 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);
10535 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
10536 Debug_PolygonEnd();
10538 // this calculates the right vector from the shortest edge
10539 // and the up vector from the edge midpoints
10540 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10541 VectorNormalize(right);
10542 VectorSubtract(end, start, up);
10543 VectorNormalize(up);
10544 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10545 VectorSubtract(rsurface.localvieworigin, center, forward);
10546 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10547 VectorNegate(forward, forward);
10548 VectorReflect(forward, 0, up, forward);
10549 VectorNormalize(forward);
10550 CrossProduct(up, forward, newright);
10551 VectorNormalize(newright);
10553 Debug_PolygonBegin(NULL, 0);
10554 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);
10555 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
10556 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
10557 Debug_PolygonEnd();
10560 Debug_PolygonBegin(NULL, 0);
10561 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
10562 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
10563 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
10564 Debug_PolygonEnd();
10566 // rotate the quad around the up axis vector, this is made
10567 // especially easy by the fact we know the quad is flat,
10568 // so we only have to subtract the center position and
10569 // measure distance along the right vector, and then
10570 // multiply that by the newright vector and add back the
10572 // we also need to subtract the old position to undo the
10573 // displacement from the center, which we do with a
10574 // DotProduct, the subtraction/addition of center is also
10575 // optimized into DotProducts here
10576 l = DotProduct(right, center);
10577 for (i = 0;i < 4;i++)
10579 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
10580 f = DotProduct(right, v1) - l;
10581 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10584 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);
10585 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);
10587 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10588 rsurface.vertex3f_bufferobject = 0;
10589 rsurface.vertex3f_bufferoffset = 0;
10590 rsurface.svector3f = rsurface.array_deformedsvector3f;
10591 rsurface.svector3f_bufferobject = 0;
10592 rsurface.svector3f_bufferoffset = 0;
10593 rsurface.tvector3f = rsurface.array_deformedtvector3f;
10594 rsurface.tvector3f_bufferobject = 0;
10595 rsurface.tvector3f_bufferoffset = 0;
10596 rsurface.normal3f = rsurface.array_deformednormal3f;
10597 rsurface.normal3f_bufferobject = 0;
10598 rsurface.normal3f_bufferoffset = 0;
10600 case Q3DEFORM_NORMAL:
10601 // deform the normals to make reflections wavey
10602 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10604 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10605 for (j = 0;j < surface->num_vertices;j++)
10608 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
10609 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
10610 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
10611 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10612 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10613 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10614 VectorNormalize(normal);
10616 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);
10618 rsurface.svector3f = rsurface.array_deformedsvector3f;
10619 rsurface.svector3f_bufferobject = 0;
10620 rsurface.svector3f_bufferoffset = 0;
10621 rsurface.tvector3f = rsurface.array_deformedtvector3f;
10622 rsurface.tvector3f_bufferobject = 0;
10623 rsurface.tvector3f_bufferoffset = 0;
10624 rsurface.normal3f = rsurface.array_deformednormal3f;
10625 rsurface.normal3f_bufferobject = 0;
10626 rsurface.normal3f_bufferoffset = 0;
10628 case Q3DEFORM_WAVE:
10629 // deform vertex array to make wavey water and flags and such
10630 waveparms[0] = deform->waveparms[0];
10631 waveparms[1] = deform->waveparms[1];
10632 waveparms[2] = deform->waveparms[2];
10633 waveparms[3] = deform->waveparms[3];
10634 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10635 break; // if wavefunc is a nop, don't make a dynamic vertex array
10636 // this is how a divisor of vertex influence on deformation
10637 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10638 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10639 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10641 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10642 for (j = 0;j < surface->num_vertices;j++)
10644 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
10645 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
10646 // if the wavefunc depends on time, evaluate it per-vertex
10649 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
10650 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10652 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
10655 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10656 rsurface.vertex3f_bufferobject = 0;
10657 rsurface.vertex3f_bufferoffset = 0;
10659 case Q3DEFORM_BULGE:
10660 // deform vertex array to make the surface have moving bulges
10661 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10663 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10664 for (j = 0;j < surface->num_vertices;j++)
10666 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
10667 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10670 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10671 rsurface.vertex3f_bufferobject = 0;
10672 rsurface.vertex3f_bufferoffset = 0;
10674 case Q3DEFORM_MOVE:
10675 // deform vertex array
10676 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10677 break; // if wavefunc is a nop, don't make a dynamic vertex array
10678 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10679 VectorScale(deform->parms, scale, waveparms);
10680 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10682 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10683 for (j = 0;j < surface->num_vertices;j++)
10684 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10686 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10687 rsurface.vertex3f_bufferobject = 0;
10688 rsurface.vertex3f_bufferoffset = 0;
10692 // generate texcoords based on the chosen texcoord source
10693 switch(rsurface.texture->tcgen.tcgen)
10696 case Q3TCGEN_TEXTURE:
10697 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10698 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
10699 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
10701 case Q3TCGEN_LIGHTMAP:
10702 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
10703 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10704 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10706 case Q3TCGEN_VECTOR:
10707 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10709 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10710 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)
10712 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10713 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10716 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10717 rsurface.texcoordtexture2f_bufferobject = 0;
10718 rsurface.texcoordtexture2f_bufferoffset = 0;
10720 case Q3TCGEN_ENVIRONMENT:
10721 // make environment reflections using a spheremap
10722 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10724 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10725 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10726 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10727 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10728 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10730 // identical to Q3A's method, but executed in worldspace so
10731 // carried models can be shiny too
10733 float viewer[3], d, reflected[3], worldreflected[3];
10735 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10736 // VectorNormalize(viewer);
10738 d = DotProduct(normal, viewer);
10740 reflected[0] = normal[0]*2*d - viewer[0];
10741 reflected[1] = normal[1]*2*d - viewer[1];
10742 reflected[2] = normal[2]*2*d - viewer[2];
10743 // note: this is proportinal to viewer, so we can normalize later
10745 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10746 VectorNormalize(worldreflected);
10748 // note: this sphere map only uses world x and z!
10749 // so positive and negative y will LOOK THE SAME.
10750 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10751 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10754 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10755 rsurface.texcoordtexture2f_bufferobject = 0;
10756 rsurface.texcoordtexture2f_bufferoffset = 0;
10759 // the only tcmod that needs software vertex processing is turbulent, so
10760 // check for it here and apply the changes if needed
10761 // and we only support that as the first one
10762 // (handling a mixture of turbulent and other tcmods would be problematic
10763 // without punting it entirely to a software path)
10764 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10766 amplitude = rsurface.texture->tcmods[0].parms[1];
10767 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10768 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10770 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10771 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)
10773 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10774 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10777 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10778 rsurface.texcoordtexture2f_bufferobject = 0;
10779 rsurface.texcoordtexture2f_bufferoffset = 0;
10781 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10782 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10783 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10784 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10787 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10790 const msurface_t *surface = texturesurfacelist[0];
10791 const msurface_t *surface2;
10796 // TODO: lock all array ranges before render, rather than on each surface
10797 if (texturenumsurfaces == 1)
10798 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);
10799 else if (r_batchmode.integer == 2)
10801 #define MAXBATCHTRIANGLES 65536
10802 int batchtriangles = 0;
10803 static int batchelements[MAXBATCHTRIANGLES*3];
10804 for (i = 0;i < texturenumsurfaces;i = j)
10806 surface = texturesurfacelist[i];
10808 if (surface->num_triangles > MAXBATCHTRIANGLES)
10810 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);
10813 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10814 batchtriangles = surface->num_triangles;
10815 firstvertex = surface->num_firstvertex;
10816 endvertex = surface->num_firstvertex + surface->num_vertices;
10817 for (;j < texturenumsurfaces;j++)
10819 surface2 = texturesurfacelist[j];
10820 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10822 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10823 batchtriangles += surface2->num_triangles;
10824 firstvertex = min(firstvertex, surface2->num_firstvertex);
10825 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10827 surface2 = texturesurfacelist[j-1];
10828 numvertices = endvertex - firstvertex;
10829 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10832 else if (r_batchmode.integer == 1)
10834 for (i = 0;i < texturenumsurfaces;i = j)
10836 surface = texturesurfacelist[i];
10837 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10838 if (texturesurfacelist[j] != surface2)
10840 surface2 = texturesurfacelist[j-1];
10841 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10842 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10843 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10848 for (i = 0;i < texturenumsurfaces;i++)
10850 surface = texturesurfacelist[i];
10851 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);
10856 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10858 switch(vid.renderpath)
10860 case RENDERPATH_CGGL:
10862 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10863 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10866 case RENDERPATH_GL20:
10867 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10868 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10870 case RENDERPATH_GL13:
10871 case RENDERPATH_GL11:
10872 R_Mesh_TexBind(0, surface->lightmaptexture);
10877 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10879 // pick the closest matching water plane and bind textures
10880 int planeindex, vertexindex;
10884 r_waterstate_waterplane_t *p, *bestp;
10887 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10889 if(p->camera_entity != rsurface.texture->camera_entity)
10892 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10894 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10895 d += fabs(PlaneDiff(vert, &p->plane));
10897 if (bestd > d || !bestp)
10903 switch(vid.renderpath)
10905 case RENDERPATH_CGGL:
10907 if (r_cg_permutation->fp_Texture_Refraction) {CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR}
10908 else if (r_cg_permutation->fp_Texture_First) {CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR}
10909 if (r_cg_permutation->fp_Texture_Reflection) {CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR}
10912 case RENDERPATH_GL20:
10913 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10914 else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
10915 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10917 case RENDERPATH_GL13:
10918 case RENDERPATH_GL11:
10923 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10926 const msurface_t *surface;
10927 if (r_waterstate.renderingscene)
10929 for (i = 0;i < texturenumsurfaces;i++)
10931 surface = texturesurfacelist[i];
10932 RSurf_BindLightmapForSurface(surface);
10933 RSurf_BindReflectionForSurface(surface);
10934 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);
10938 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10942 const msurface_t *surface = texturesurfacelist[0];
10943 const msurface_t *surface2;
10948 if (texturenumsurfaces == 1)
10950 RSurf_BindLightmapForSurface(surface);
10951 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);
10953 else if (r_batchmode.integer == 2)
10955 int batchtriangles = 0;
10956 static int batchelements[MAXBATCHTRIANGLES*3];
10957 for (i = 0;i < texturenumsurfaces;i = j)
10959 surface = texturesurfacelist[i];
10960 RSurf_BindLightmapForSurface(surface);
10962 if (surface->num_triangles > MAXBATCHTRIANGLES)
10964 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);
10967 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10968 batchtriangles = surface->num_triangles;
10969 firstvertex = surface->num_firstvertex;
10970 endvertex = surface->num_firstvertex + surface->num_vertices;
10971 for (;j < texturenumsurfaces;j++)
10973 surface2 = texturesurfacelist[j];
10974 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10976 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10977 batchtriangles += surface2->num_triangles;
10978 firstvertex = min(firstvertex, surface2->num_firstvertex);
10979 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10981 surface2 = texturesurfacelist[j-1];
10982 numvertices = endvertex - firstvertex;
10983 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10986 else if (r_batchmode.integer == 1)
10989 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10990 for (i = 0;i < texturenumsurfaces;i = j)
10992 surface = texturesurfacelist[i];
10993 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10994 if (texturesurfacelist[j] != surface2)
10996 Con_Printf(" %i", j - i);
10999 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
11001 for (i = 0;i < texturenumsurfaces;i = j)
11003 surface = texturesurfacelist[i];
11004 RSurf_BindLightmapForSurface(surface);
11005 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
11006 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
11009 Con_Printf(" %i", j - i);
11011 surface2 = texturesurfacelist[j-1];
11012 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
11013 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
11014 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
11022 for (i = 0;i < texturenumsurfaces;i++)
11024 surface = texturesurfacelist[i];
11025 RSurf_BindLightmapForSurface(surface);
11026 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);
11031 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11034 int texturesurfaceindex;
11035 if (r_showsurfaces.integer == 2)
11037 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11039 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11040 for (j = 0;j < surface->num_triangles;j++)
11042 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
11043 GL_Color(f, f, f, 1);
11044 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
11050 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11052 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11053 int k = (int)(((size_t)surface) / sizeof(msurface_t));
11054 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);
11055 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);
11060 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11062 int texturesurfaceindex;
11066 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11068 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11069 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)
11077 rsurface.lightmapcolor4f = rsurface.array_color4f;
11078 rsurface.lightmapcolor4f_bufferobject = 0;
11079 rsurface.lightmapcolor4f_bufferoffset = 0;
11082 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11084 int texturesurfaceindex;
11090 if (rsurface.lightmapcolor4f)
11092 // generate color arrays for the surfaces in this list
11093 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11095 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11096 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)
11098 f = RSurf_FogVertex(v);
11108 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11110 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11111 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)
11113 f = RSurf_FogVertex(v);
11121 rsurface.lightmapcolor4f = rsurface.array_color4f;
11122 rsurface.lightmapcolor4f_bufferobject = 0;
11123 rsurface.lightmapcolor4f_bufferoffset = 0;
11126 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11128 int texturesurfaceindex;
11134 if (!rsurface.lightmapcolor4f)
11136 // generate color arrays for the surfaces in this list
11137 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11139 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11140 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)
11142 f = RSurf_FogVertex(v);
11143 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11144 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11145 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11149 rsurface.lightmapcolor4f = rsurface.array_color4f;
11150 rsurface.lightmapcolor4f_bufferobject = 0;
11151 rsurface.lightmapcolor4f_bufferoffset = 0;
11154 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
11156 int texturesurfaceindex;
11160 if (!rsurface.lightmapcolor4f)
11162 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11164 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11165 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)
11173 rsurface.lightmapcolor4f = rsurface.array_color4f;
11174 rsurface.lightmapcolor4f_bufferobject = 0;
11175 rsurface.lightmapcolor4f_bufferoffset = 0;
11178 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11180 int texturesurfaceindex;
11184 if (!rsurface.lightmapcolor4f)
11186 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11188 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11189 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)
11191 c2[0] = c[0] + r_refdef.scene.ambient;
11192 c2[1] = c[1] + r_refdef.scene.ambient;
11193 c2[2] = c[2] + r_refdef.scene.ambient;
11197 rsurface.lightmapcolor4f = rsurface.array_color4f;
11198 rsurface.lightmapcolor4f_bufferobject = 0;
11199 rsurface.lightmapcolor4f_bufferoffset = 0;
11202 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11205 rsurface.lightmapcolor4f = NULL;
11206 rsurface.lightmapcolor4f_bufferobject = 0;
11207 rsurface.lightmapcolor4f_bufferoffset = 0;
11208 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11209 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11210 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11211 GL_Color(r, g, b, a);
11212 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11215 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11217 // TODO: optimize applyfog && applycolor case
11218 // just apply fog if necessary, and tint the fog color array if necessary
11219 rsurface.lightmapcolor4f = NULL;
11220 rsurface.lightmapcolor4f_bufferobject = 0;
11221 rsurface.lightmapcolor4f_bufferoffset = 0;
11222 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11223 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11224 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11225 GL_Color(r, g, b, a);
11226 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11229 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11231 int texturesurfaceindex;
11235 if (texturesurfacelist[0]->lightmapinfo)
11237 // generate color arrays for the surfaces in this list
11238 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11240 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11241 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
11243 if (surface->lightmapinfo->samples)
11245 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
11246 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
11247 VectorScale(lm, scale, c);
11248 if (surface->lightmapinfo->styles[1] != 255)
11250 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11252 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
11253 VectorMA(c, scale, lm, c);
11254 if (surface->lightmapinfo->styles[2] != 255)
11257 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
11258 VectorMA(c, scale, lm, c);
11259 if (surface->lightmapinfo->styles[3] != 255)
11262 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
11263 VectorMA(c, scale, lm, c);
11273 rsurface.lightmapcolor4f = rsurface.array_color4f;
11274 rsurface.lightmapcolor4f_bufferobject = 0;
11275 rsurface.lightmapcolor4f_bufferoffset = 0;
11279 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11280 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11281 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11283 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11284 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11285 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11286 GL_Color(r, g, b, a);
11287 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11290 static void RSurf_DrawBatch_GL11_ApplyFakeLight(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11292 int texturesurfaceindex;
11301 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11303 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11304 int numverts = surface->num_vertices;
11305 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
11306 n = rsurface.normal3f + 3 * surface->num_firstvertex;
11307 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
11308 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
11310 f = -DotProduct(r_refdef.view.forward, n);
11312 f = f * 0.85 + 0.15; // work around so stuff won't get black
11313 f *= r_refdef.lightmapintensity;
11314 Vector4Set(c, f, f, f, 1);
11318 rsurface.lightmapcolor4f = rsurface.array_color4f;
11319 rsurface.lightmapcolor4f_bufferobject = 0;
11320 rsurface.lightmapcolor4f_bufferoffset = 0;
11323 static void RSurf_DrawBatch_GL11_FakeLight(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11325 RSurf_DrawBatch_GL11_ApplyFakeLight(texturenumsurfaces, texturesurfacelist);
11326 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11327 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11328 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11329 GL_Color(r, g, b, a);
11330 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11333 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
11335 int texturesurfaceindex;
11342 vec3_t ambientcolor;
11343 vec3_t diffusecolor;
11347 VectorCopy(rsurface.modellight_lightdir, lightdir);
11348 f = 0.5f * r_refdef.lightmapintensity;
11349 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11350 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11351 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11352 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11353 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11354 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11356 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
11358 // generate color arrays for the surfaces in this list
11359 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11361 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11362 int numverts = surface->num_vertices;
11363 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
11364 n = rsurface.normal3f + 3 * surface->num_firstvertex;
11365 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
11366 // q3-style directional shading
11367 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
11369 if ((f = DotProduct(n, lightdir)) > 0)
11370 VectorMA(ambientcolor, f, diffusecolor, c);
11372 VectorCopy(ambientcolor, c);
11380 rsurface.lightmapcolor4f = rsurface.array_color4f;
11381 rsurface.lightmapcolor4f_bufferobject = 0;
11382 rsurface.lightmapcolor4f_bufferoffset = 0;
11383 *applycolor = false;
11387 *r = ambientcolor[0];
11388 *g = ambientcolor[1];
11389 *b = ambientcolor[2];
11390 rsurface.lightmapcolor4f = NULL;
11391 rsurface.lightmapcolor4f_bufferobject = 0;
11392 rsurface.lightmapcolor4f_bufferoffset = 0;
11396 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11398 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
11399 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11400 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11401 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11402 GL_Color(r, g, b, a);
11403 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11406 void RSurf_SetupDepthAndCulling(void)
11408 // submodels are biased to avoid z-fighting with world surfaces that they
11409 // may be exactly overlapping (avoids z-fighting artifacts on certain
11410 // doors and things in Quake maps)
11411 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11412 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11413 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11414 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11417 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11419 // transparent sky would be ridiculous
11420 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11422 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11423 skyrenderlater = true;
11424 RSurf_SetupDepthAndCulling();
11425 GL_DepthMask(true);
11426 // LordHavoc: HalfLife maps have freaky skypolys so don't use
11427 // skymasking on them, and Quake3 never did sky masking (unlike
11428 // software Quake and software Quake2), so disable the sky masking
11429 // in Quake3 maps as it causes problems with q3map2 sky tricks,
11430 // and skymasking also looks very bad when noclipping outside the
11431 // level, so don't use it then either.
11432 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
11434 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
11435 R_Mesh_ColorPointer(NULL, 0, 0);
11436 R_Mesh_ResetTextureState();
11437 if (skyrendermasked)
11439 R_SetupShader_DepthOrShadow();
11440 // depth-only (masking)
11441 GL_ColorMask(0,0,0,0);
11442 // just to make sure that braindead drivers don't draw
11443 // anything despite that colormask...
11444 GL_BlendFunc(GL_ZERO, GL_ONE);
11448 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11450 GL_BlendFunc(GL_ONE, GL_ZERO);
11452 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11453 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11454 if (skyrendermasked)
11455 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11457 R_Mesh_ResetTextureState();
11458 GL_Color(1, 1, 1, 1);
11461 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
11462 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
11463 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11465 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
11467 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
11470 // render screenspace normalmap to texture
11471 GL_DepthMask(true);
11472 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
11473 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11475 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
11477 // render water or distortion background, then blend surface on top
11478 GL_DepthMask(true);
11479 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
11480 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11481 GL_DepthMask(false);
11482 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11483 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11484 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11486 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11490 // render surface normally
11491 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11492 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11493 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
11494 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11495 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11496 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11498 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11502 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11504 // OpenGL 1.3 path - anything not completely ancient
11505 int texturesurfaceindex;
11506 qboolean applycolor;
11509 const texturelayer_t *layer;
11510 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11512 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11515 int layertexrgbscale;
11516 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11518 if (layerindex == 0)
11519 GL_AlphaTest(true);
11522 GL_AlphaTest(false);
11523 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11526 GL_DepthMask(layer->depthmask && writedepth);
11527 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11528 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11530 layertexrgbscale = 4;
11531 VectorScale(layer->color, 0.25f, layercolor);
11533 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11535 layertexrgbscale = 2;
11536 VectorScale(layer->color, 0.5f, layercolor);
11540 layertexrgbscale = 1;
11541 VectorScale(layer->color, 1.0f, layercolor);
11543 layercolor[3] = layer->color[3];
11544 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11545 R_Mesh_ColorPointer(NULL, 0, 0);
11546 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11547 switch (layer->type)
11549 case TEXTURELAYERTYPE_LITTEXTURE:
11550 // single-pass lightmapped texture with 2x rgbscale
11551 R_Mesh_TexBind(0, r_texture_white);
11552 R_Mesh_TexMatrix(0, NULL);
11553 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11554 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11555 R_Mesh_TexBind(1, layer->texture);
11556 R_Mesh_TexMatrix(1, &layer->texmatrix);
11557 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11558 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11559 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11560 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11561 else if (FAKELIGHT_ENABLED)
11562 RSurf_DrawBatch_GL11_FakeLight(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11563 else if (rsurface.uselightmaptexture)
11564 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11566 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11568 case TEXTURELAYERTYPE_TEXTURE:
11569 // singletexture unlit texture with transparency support
11570 R_Mesh_TexBind(0, layer->texture);
11571 R_Mesh_TexMatrix(0, &layer->texmatrix);
11572 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11573 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11574 R_Mesh_TexBind(1, 0);
11575 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11576 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11578 case TEXTURELAYERTYPE_FOG:
11579 // singletexture fogging
11580 if (layer->texture)
11582 R_Mesh_TexBind(0, layer->texture);
11583 R_Mesh_TexMatrix(0, &layer->texmatrix);
11584 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11585 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11589 R_Mesh_TexBind(0, 0);
11590 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11592 R_Mesh_TexBind(1, 0);
11593 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11594 // generate a color array for the fog pass
11595 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11596 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11602 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11603 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)
11605 f = 1 - RSurf_FogVertex(v);
11606 c[0] = layercolor[0];
11607 c[1] = layercolor[1];
11608 c[2] = layercolor[2];
11609 c[3] = f * layercolor[3];
11612 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11615 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11619 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11621 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11622 GL_AlphaTest(false);
11626 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11628 // OpenGL 1.1 - crusty old voodoo path
11629 int texturesurfaceindex;
11632 const texturelayer_t *layer;
11633 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11635 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11637 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11639 if (layerindex == 0)
11640 GL_AlphaTest(true);
11643 GL_AlphaTest(false);
11644 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11647 GL_DepthMask(layer->depthmask && writedepth);
11648 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11649 R_Mesh_ColorPointer(NULL, 0, 0);
11650 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11651 switch (layer->type)
11653 case TEXTURELAYERTYPE_LITTEXTURE:
11654 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
11656 // two-pass lit texture with 2x rgbscale
11657 // first the lightmap pass
11658 R_Mesh_TexBind(0, r_texture_white);
11659 R_Mesh_TexMatrix(0, NULL);
11660 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11661 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11662 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11663 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11664 else if (FAKELIGHT_ENABLED)
11665 RSurf_DrawBatch_GL11_FakeLight(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11666 else if (rsurface.uselightmaptexture)
11667 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11669 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11670 // then apply the texture to it
11671 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11672 R_Mesh_TexBind(0, layer->texture);
11673 R_Mesh_TexMatrix(0, &layer->texmatrix);
11674 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11675 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11676 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);
11680 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11681 R_Mesh_TexBind(0, layer->texture);
11682 R_Mesh_TexMatrix(0, &layer->texmatrix);
11683 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11684 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11685 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11686 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);
11688 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);
11691 case TEXTURELAYERTYPE_TEXTURE:
11692 // singletexture unlit texture with transparency support
11693 R_Mesh_TexBind(0, layer->texture);
11694 R_Mesh_TexMatrix(0, &layer->texmatrix);
11695 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11696 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11697 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);
11699 case TEXTURELAYERTYPE_FOG:
11700 // singletexture fogging
11701 if (layer->texture)
11703 R_Mesh_TexBind(0, layer->texture);
11704 R_Mesh_TexMatrix(0, &layer->texmatrix);
11705 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11706 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11710 R_Mesh_TexBind(0, 0);
11711 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11713 // generate a color array for the fog pass
11714 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11715 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11721 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11722 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)
11724 f = 1 - RSurf_FogVertex(v);
11725 c[0] = layer->color[0];
11726 c[1] = layer->color[1];
11727 c[2] = layer->color[2];
11728 c[3] = f * layer->color[3];
11731 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11734 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11738 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11740 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11741 GL_AlphaTest(false);
11745 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11749 GL_AlphaTest(false);
11750 R_Mesh_ColorPointer(NULL, 0, 0);
11751 R_Mesh_ResetTextureState();
11752 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11754 if(rsurface.texture && rsurface.texture->currentskinframe)
11756 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11757 c[3] *= rsurface.texture->currentalpha;
11767 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11769 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11770 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11771 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11774 // brighten it up (as texture value 127 means "unlit")
11775 c[0] *= 2 * r_refdef.view.colorscale;
11776 c[1] *= 2 * r_refdef.view.colorscale;
11777 c[2] *= 2 * r_refdef.view.colorscale;
11779 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11780 c[3] *= r_wateralpha.value;
11782 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11784 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11785 GL_DepthMask(false);
11787 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11789 GL_BlendFunc(GL_ONE, GL_ONE);
11790 GL_DepthMask(false);
11792 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11794 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11795 GL_DepthMask(false);
11797 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11799 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11800 GL_DepthMask(false);
11804 GL_BlendFunc(GL_ONE, GL_ZERO);
11805 GL_DepthMask(writedepth);
11808 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11810 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11812 rsurface.lightmapcolor4f = NULL;
11813 rsurface.lightmapcolor4f_bufferobject = 0;
11814 rsurface.lightmapcolor4f_bufferoffset = 0;
11816 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11818 qboolean applycolor = true;
11821 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11823 r_refdef.lightmapintensity = 1;
11824 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11825 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11827 else if (FAKELIGHT_ENABLED)
11829 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11831 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11832 RSurf_DrawBatch_GL11_ApplyFakeLight(texturenumsurfaces, texturesurfacelist);
11833 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11837 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11839 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11840 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11841 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11844 if(!rsurface.lightmapcolor4f)
11845 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11847 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11848 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11849 if(r_refdef.fogenabled)
11850 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11852 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11853 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11856 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11859 RSurf_SetupDepthAndCulling();
11860 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11862 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11865 switch (vid.renderpath)
11867 case RENDERPATH_GL20:
11868 case RENDERPATH_CGGL:
11869 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11871 case RENDERPATH_GL13:
11872 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11874 case RENDERPATH_GL11:
11875 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11881 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11884 RSurf_SetupDepthAndCulling();
11885 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11887 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11890 switch (vid.renderpath)
11892 case RENDERPATH_GL20:
11893 case RENDERPATH_CGGL:
11894 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11896 case RENDERPATH_GL13:
11897 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11899 case RENDERPATH_GL11:
11900 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11906 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11909 int texturenumsurfaces, endsurface;
11910 texture_t *texture;
11911 const msurface_t *surface;
11912 #define MAXBATCH_TRANSPARENTSURFACES 256
11913 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
11915 // if the model is static it doesn't matter what value we give for
11916 // wantnormals and wanttangents, so this logic uses only rules applicable
11917 // to a model, knowing that they are meaningless otherwise
11918 if (ent == r_refdef.scene.worldentity)
11919 RSurf_ActiveWorldEntity();
11920 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11921 RSurf_ActiveModelEntity(ent, false, false, false);
11924 switch (vid.renderpath)
11926 case RENDERPATH_GL20:
11927 case RENDERPATH_CGGL:
11928 RSurf_ActiveModelEntity(ent, true, true, false);
11930 case RENDERPATH_GL13:
11931 case RENDERPATH_GL11:
11932 RSurf_ActiveModelEntity(ent, true, false, false);
11937 if (r_transparentdepthmasking.integer)
11939 qboolean setup = false;
11940 for (i = 0;i < numsurfaces;i = j)
11943 surface = rsurface.modelsurfaces + surfacelist[i];
11944 texture = surface->texture;
11945 rsurface.texture = R_GetCurrentTexture(texture);
11946 // scan ahead until we find a different texture
11947 endsurface = min(i + 1024, numsurfaces);
11948 texturenumsurfaces = 0;
11949 texturesurfacelist[texturenumsurfaces++] = surface;
11950 if(FAKELIGHT_ENABLED)
11952 rsurface.uselightmaptexture = false;
11953 for (;j < endsurface;j++)
11955 surface = rsurface.modelsurfaces + surfacelist[j];
11956 if (texture != surface->texture)
11958 texturesurfacelist[texturenumsurfaces++] = surface;
11963 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11964 for (;j < endsurface;j++)
11966 surface = rsurface.modelsurfaces + surfacelist[j];
11967 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11969 texturesurfacelist[texturenumsurfaces++] = surface;
11972 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11974 // render the range of surfaces as depth
11978 GL_ColorMask(0,0,0,0);
11980 GL_DepthTest(true);
11981 GL_BlendFunc(GL_ONE, GL_ZERO);
11982 GL_DepthMask(true);
11983 GL_AlphaTest(false);
11984 R_Mesh_ColorPointer(NULL, 0, 0);
11985 R_Mesh_ResetTextureState();
11986 R_SetupShader_DepthOrShadow();
11988 RSurf_SetupDepthAndCulling();
11989 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11990 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11993 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11996 for (i = 0;i < numsurfaces;i = j)
11999 surface = rsurface.modelsurfaces + surfacelist[i];
12000 texture = surface->texture;
12001 rsurface.texture = R_GetCurrentTexture(texture);
12002 // scan ahead until we find a different texture
12003 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12004 texturenumsurfaces = 0;
12005 texturesurfacelist[texturenumsurfaces++] = surface;
12006 if(FAKELIGHT_ENABLED)
12008 rsurface.uselightmaptexture = false;
12009 for (;j < endsurface;j++)
12011 surface = rsurface.modelsurfaces + surfacelist[j];
12012 if (texture != surface->texture)
12014 texturesurfacelist[texturenumsurfaces++] = surface;
12019 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12020 for (;j < endsurface;j++)
12022 surface = rsurface.modelsurfaces + surfacelist[j];
12023 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
12025 texturesurfacelist[texturenumsurfaces++] = surface;
12028 // render the range of surfaces
12029 if (ent == r_refdef.scene.worldentity)
12030 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12032 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12034 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12035 GL_AlphaTest(false);
12038 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12040 // transparent surfaces get pushed off into the transparent queue
12041 int surfacelistindex;
12042 const msurface_t *surface;
12043 vec3_t tempcenter, center;
12044 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12046 surface = texturesurfacelist[surfacelistindex];
12047 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12048 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12049 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12050 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12051 if (queueentity->transparent_offset) // transparent offset
12053 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12054 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12055 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12057 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12061 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12063 const entity_render_t *queueentity = r_refdef.scene.worldentity;
12067 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12069 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12071 RSurf_SetupDepthAndCulling();
12072 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12073 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12077 if (!rsurface.texture->currentnumlayers)
12079 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12080 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12082 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12084 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
12086 RSurf_SetupDepthAndCulling();
12087 GL_AlphaTest(false);
12088 R_Mesh_ColorPointer(NULL, 0, 0);
12089 R_Mesh_ResetTextureState();
12090 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12091 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12092 GL_DepthMask(true);
12093 GL_BlendFunc(GL_ONE, GL_ZERO);
12094 GL_Color(0, 0, 0, 1);
12095 GL_DepthTest(writedepth);
12096 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12098 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
12100 RSurf_SetupDepthAndCulling();
12101 GL_AlphaTest(false);
12102 R_Mesh_ColorPointer(NULL, 0, 0);
12103 R_Mesh_ResetTextureState();
12104 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12105 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12106 GL_DepthMask(true);
12107 GL_BlendFunc(GL_ONE, GL_ZERO);
12108 GL_DepthTest(true);
12109 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
12111 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
12112 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12113 else if (!rsurface.texture->currentnumlayers)
12115 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12117 // in the deferred case, transparent surfaces were queued during prepass
12118 if (!r_shadow_usingdeferredprepass)
12119 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12123 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12124 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12129 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12132 texture_t *texture;
12133 // break the surface list down into batches by texture and use of lightmapping
12134 for (i = 0;i < numsurfaces;i = j)
12137 // texture is the base texture pointer, rsurface.texture is the
12138 // current frame/skin the texture is directing us to use (for example
12139 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12140 // use skin 1 instead)
12141 texture = surfacelist[i]->texture;
12142 rsurface.texture = R_GetCurrentTexture(texture);
12143 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12145 // if this texture is not the kind we want, skip ahead to the next one
12146 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12150 if(FAKELIGHT_ENABLED || depthonly || prepass)
12152 rsurface.uselightmaptexture = false;
12153 // simply scan ahead until we find a different texture or lightmap state
12154 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12159 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12160 // simply scan ahead until we find a different texture or lightmap state
12161 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
12164 // render the range of surfaces
12165 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12169 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12174 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12176 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12178 RSurf_SetupDepthAndCulling();
12179 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12180 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12184 if (!rsurface.texture->currentnumlayers)
12186 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12187 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12189 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12191 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
12193 RSurf_SetupDepthAndCulling();
12194 GL_AlphaTest(false);
12195 R_Mesh_ColorPointer(NULL, 0, 0);
12196 R_Mesh_ResetTextureState();
12197 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12198 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12199 GL_DepthMask(true);
12200 GL_BlendFunc(GL_ONE, GL_ZERO);
12201 GL_Color(0, 0, 0, 1);
12202 GL_DepthTest(writedepth);
12203 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12205 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12207 RSurf_SetupDepthAndCulling();
12208 GL_AlphaTest(false);
12209 R_Mesh_ColorPointer(NULL, 0, 0);
12210 R_Mesh_ResetTextureState();
12211 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12212 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12213 GL_DepthMask(true);
12214 GL_BlendFunc(GL_ONE, GL_ZERO);
12215 GL_DepthTest(true);
12216 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
12218 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
12219 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12220 else if (!rsurface.texture->currentnumlayers)
12222 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12224 // in the deferred case, transparent surfaces were queued during prepass
12225 if (!r_shadow_usingdeferredprepass)
12226 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12230 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12231 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12236 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12239 texture_t *texture;
12240 // break the surface list down into batches by texture and use of lightmapping
12241 for (i = 0;i < numsurfaces;i = j)
12244 // texture is the base texture pointer, rsurface.texture is the
12245 // current frame/skin the texture is directing us to use (for example
12246 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12247 // use skin 1 instead)
12248 texture = surfacelist[i]->texture;
12249 rsurface.texture = R_GetCurrentTexture(texture);
12250 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12252 // if this texture is not the kind we want, skip ahead to the next one
12253 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12257 if(FAKELIGHT_ENABLED || depthonly || prepass)
12259 rsurface.uselightmaptexture = false;
12260 // simply scan ahead until we find a different texture or lightmap state
12261 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12266 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12267 // simply scan ahead until we find a different texture or lightmap state
12268 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
12271 // render the range of surfaces
12272 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12276 float locboxvertex3f[6*4*3] =
12278 1,0,1, 1,0,0, 1,1,0, 1,1,1,
12279 0,1,1, 0,1,0, 0,0,0, 0,0,1,
12280 1,1,1, 1,1,0, 0,1,0, 0,1,1,
12281 0,0,1, 0,0,0, 1,0,0, 1,0,1,
12282 0,0,1, 1,0,1, 1,1,1, 0,1,1,
12283 1,0,0, 0,0,0, 0,1,0, 1,1,0
12286 unsigned short locboxelements[6*2*3] =
12291 12,13,14, 12,14,15,
12292 16,17,18, 16,18,19,
12296 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12299 cl_locnode_t *loc = (cl_locnode_t *)ent;
12301 float vertex3f[6*4*3];
12303 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12304 GL_DepthMask(false);
12305 GL_DepthRange(0, 1);
12306 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12307 GL_DepthTest(true);
12308 GL_CullFace(GL_NONE);
12309 R_EntityMatrix(&identitymatrix);
12311 R_Mesh_VertexPointer(vertex3f, 0, 0);
12312 R_Mesh_ColorPointer(NULL, 0, 0);
12313 R_Mesh_ResetTextureState();
12314 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12316 i = surfacelist[0];
12317 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12318 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12319 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12320 surfacelist[0] < 0 ? 0.5f : 0.125f);
12322 if (VectorCompare(loc->mins, loc->maxs))
12324 VectorSet(size, 2, 2, 2);
12325 VectorMA(loc->mins, -0.5f, size, mins);
12329 VectorCopy(loc->mins, mins);
12330 VectorSubtract(loc->maxs, loc->mins, size);
12333 for (i = 0;i < 6*4*3;)
12334 for (j = 0;j < 3;j++, i++)
12335 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12337 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
12340 void R_DrawLocs(void)
12343 cl_locnode_t *loc, *nearestloc;
12345 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12346 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12348 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12349 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12353 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12355 if (decalsystem->decals)
12356 Mem_Free(decalsystem->decals);
12357 memset(decalsystem, 0, sizeof(*decalsystem));
12360 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)
12363 tridecal_t *decals;
12366 // expand or initialize the system
12367 if (decalsystem->maxdecals <= decalsystem->numdecals)
12369 decalsystem_t old = *decalsystem;
12370 qboolean useshortelements;
12371 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12372 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12373 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)));
12374 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12375 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12376 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12377 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12378 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12379 if (decalsystem->numdecals)
12380 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12382 Mem_Free(old.decals);
12383 for (i = 0;i < decalsystem->maxdecals*3;i++)
12384 decalsystem->element3i[i] = i;
12385 if (useshortelements)
12386 for (i = 0;i < decalsystem->maxdecals*3;i++)
12387 decalsystem->element3s[i] = i;
12390 // grab a decal and search for another free slot for the next one
12391 decals = decalsystem->decals;
12392 decal = decalsystem->decals + (i = decalsystem->freedecal++);
12393 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12395 decalsystem->freedecal = i;
12396 if (decalsystem->numdecals <= i)
12397 decalsystem->numdecals = i + 1;
12399 // initialize the decal
12401 decal->triangleindex = triangleindex;
12402 decal->surfaceindex = surfaceindex;
12403 decal->decalsequence = decalsequence;
12404 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
12405 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
12406 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
12407 decal->color4ub[0][3] = 255;
12408 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
12409 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
12410 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
12411 decal->color4ub[1][3] = 255;
12412 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
12413 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
12414 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
12415 decal->color4ub[2][3] = 255;
12416 decal->vertex3f[0][0] = v0[0];
12417 decal->vertex3f[0][1] = v0[1];
12418 decal->vertex3f[0][2] = v0[2];
12419 decal->vertex3f[1][0] = v1[0];
12420 decal->vertex3f[1][1] = v1[1];
12421 decal->vertex3f[1][2] = v1[2];
12422 decal->vertex3f[2][0] = v2[0];
12423 decal->vertex3f[2][1] = v2[1];
12424 decal->vertex3f[2][2] = v2[2];
12425 decal->texcoord2f[0][0] = t0[0];
12426 decal->texcoord2f[0][1] = t0[1];
12427 decal->texcoord2f[1][0] = t1[0];
12428 decal->texcoord2f[1][1] = t1[1];
12429 decal->texcoord2f[2][0] = t2[0];
12430 decal->texcoord2f[2][1] = t2[1];
12433 extern cvar_t cl_decals_bias;
12434 extern cvar_t cl_decals_models;
12435 extern cvar_t cl_decals_newsystem_intensitymultiplier;
12436 // baseparms, parms, temps
12437 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
12442 const float *vertex3f;
12444 float points[2][9][3];
12451 e = rsurface.modelelement3i + 3*triangleindex;
12453 vertex3f = rsurface.modelvertex3f;
12455 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12457 index = 3*e[cornerindex];
12458 VectorCopy(vertex3f + index, v[cornerindex]);
12461 //TriangleNormal(v[0], v[1], v[2], normal);
12462 //if (DotProduct(normal, localnormal) < 0.0f)
12464 // clip by each of the box planes formed from the projection matrix
12465 // if anything survives, we emit the decal
12466 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]);
12469 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]);
12472 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]);
12475 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]);
12478 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]);
12481 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]);
12484 // some part of the triangle survived, so we have to accept it...
12487 // dynamic always uses the original triangle
12489 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12491 index = 3*e[cornerindex];
12492 VectorCopy(vertex3f + index, v[cornerindex]);
12495 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12497 // convert vertex positions to texcoords
12498 Matrix4x4_Transform(projection, v[cornerindex], temp);
12499 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12500 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12501 // calculate distance fade from the projection origin
12502 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12503 f = bound(0.0f, f, 1.0f);
12504 c[cornerindex][0] = r * f;
12505 c[cornerindex][1] = g * f;
12506 c[cornerindex][2] = b * f;
12507 c[cornerindex][3] = 1.0f;
12508 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12511 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
12513 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12514 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);
12516 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)
12518 matrix4x4_t projection;
12519 decalsystem_t *decalsystem;
12522 const msurface_t *surface;
12523 const msurface_t *surfaces;
12524 const int *surfacelist;
12525 const texture_t *texture;
12527 int numsurfacelist;
12528 int surfacelistindex;
12531 float localorigin[3];
12532 float localnormal[3];
12533 float localmins[3];
12534 float localmaxs[3];
12537 float planes[6][4];
12540 int bih_triangles_count;
12541 int bih_triangles[256];
12542 int bih_surfaces[256];
12544 decalsystem = &ent->decalsystem;
12545 model = ent->model;
12546 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
12548 R_DecalSystem_Reset(&ent->decalsystem);
12552 if (!model->brush.data_nodes && !cl_decals_models.integer)
12554 if (decalsystem->model)
12555 R_DecalSystem_Reset(decalsystem);
12559 if (decalsystem->model != model)
12560 R_DecalSystem_Reset(decalsystem);
12561 decalsystem->model = model;
12563 RSurf_ActiveModelEntity(ent, false, false, false);
12565 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12566 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12567 VectorNormalize(localnormal);
12568 localsize = worldsize*rsurface.inversematrixscale;
12569 localmins[0] = localorigin[0] - localsize;
12570 localmins[1] = localorigin[1] - localsize;
12571 localmins[2] = localorigin[2] - localsize;
12572 localmaxs[0] = localorigin[0] + localsize;
12573 localmaxs[1] = localorigin[1] + localsize;
12574 localmaxs[2] = localorigin[2] + localsize;
12576 //VectorCopy(localnormal, planes[4]);
12577 //VectorVectors(planes[4], planes[2], planes[0]);
12578 AnglesFromVectors(angles, localnormal, NULL, false);
12579 AngleVectors(angles, planes[0], planes[2], planes[4]);
12580 VectorNegate(planes[0], planes[1]);
12581 VectorNegate(planes[2], planes[3]);
12582 VectorNegate(planes[4], planes[5]);
12583 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12584 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12585 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12586 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12587 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12588 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12593 matrix4x4_t forwardprojection;
12594 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12595 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12600 float projectionvector[4][3];
12601 VectorScale(planes[0], ilocalsize, projectionvector[0]);
12602 VectorScale(planes[2], ilocalsize, projectionvector[1]);
12603 VectorScale(planes[4], ilocalsize, projectionvector[2]);
12604 projectionvector[0][0] = planes[0][0] * ilocalsize;
12605 projectionvector[0][1] = planes[1][0] * ilocalsize;
12606 projectionvector[0][2] = planes[2][0] * ilocalsize;
12607 projectionvector[1][0] = planes[0][1] * ilocalsize;
12608 projectionvector[1][1] = planes[1][1] * ilocalsize;
12609 projectionvector[1][2] = planes[2][1] * ilocalsize;
12610 projectionvector[2][0] = planes[0][2] * ilocalsize;
12611 projectionvector[2][1] = planes[1][2] * ilocalsize;
12612 projectionvector[2][2] = planes[2][2] * ilocalsize;
12613 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12614 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12615 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12616 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12620 dynamic = model->surfmesh.isanimated;
12621 numsurfacelist = model->nummodelsurfaces;
12622 surfacelist = model->sortedmodelsurfaces;
12623 surfaces = model->data_surfaces;
12626 bih_triangles_count = -1;
12629 if(model->render_bih.numleafs)
12630 bih = &model->render_bih;
12631 else if(model->collision_bih.numleafs)
12632 bih = &model->collision_bih;
12635 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12636 if(bih_triangles_count == 0)
12638 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12640 if(bih_triangles_count > 0)
12642 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12644 surfaceindex = bih_surfaces[triangleindex];
12645 surface = surfaces + surfaceindex;
12646 texture = surface->texture;
12647 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12649 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12651 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12656 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12658 surfaceindex = surfacelist[surfacelistindex];
12659 surface = surfaces + surfaceindex;
12660 // check cull box first because it rejects more than any other check
12661 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12663 // skip transparent surfaces
12664 texture = surface->texture;
12665 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12667 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12669 numtriangles = surface->num_triangles;
12670 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12671 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12676 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12677 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)
12679 int renderentityindex;
12680 float worldmins[3];
12681 float worldmaxs[3];
12682 entity_render_t *ent;
12684 if (!cl_decals_newsystem.integer)
12687 worldmins[0] = worldorigin[0] - worldsize;
12688 worldmins[1] = worldorigin[1] - worldsize;
12689 worldmins[2] = worldorigin[2] - worldsize;
12690 worldmaxs[0] = worldorigin[0] + worldsize;
12691 worldmaxs[1] = worldorigin[1] + worldsize;
12692 worldmaxs[2] = worldorigin[2] + worldsize;
12694 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12696 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12698 ent = r_refdef.scene.entities[renderentityindex];
12699 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12702 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12706 typedef struct r_decalsystem_splatqueue_s
12708 vec3_t worldorigin;
12709 vec3_t worldnormal;
12715 r_decalsystem_splatqueue_t;
12717 int r_decalsystem_numqueued = 0;
12718 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12720 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)
12722 r_decalsystem_splatqueue_t *queue;
12724 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12727 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12728 VectorCopy(worldorigin, queue->worldorigin);
12729 VectorCopy(worldnormal, queue->worldnormal);
12730 Vector4Set(queue->color, r, g, b, a);
12731 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12732 queue->worldsize = worldsize;
12733 queue->decalsequence = cl.decalsequence++;
12736 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12739 r_decalsystem_splatqueue_t *queue;
12741 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12742 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);
12743 r_decalsystem_numqueued = 0;
12746 extern cvar_t cl_decals_max;
12747 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12750 decalsystem_t *decalsystem = &ent->decalsystem;
12757 if (!decalsystem->numdecals)
12760 if (r_showsurfaces.integer)
12763 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12765 R_DecalSystem_Reset(decalsystem);
12769 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12770 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12772 if (decalsystem->lastupdatetime)
12773 frametime = (cl.time - decalsystem->lastupdatetime);
12776 decalsystem->lastupdatetime = cl.time;
12777 decal = decalsystem->decals;
12778 numdecals = decalsystem->numdecals;
12780 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12782 if (decal->color4ub[0][3])
12784 decal->lived += frametime;
12785 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12787 memset(decal, 0, sizeof(*decal));
12788 if (decalsystem->freedecal > i)
12789 decalsystem->freedecal = i;
12793 decal = decalsystem->decals;
12794 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
12797 // collapse the array by shuffling the tail decals into the gaps
12800 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12801 decalsystem->freedecal++;
12802 if (decalsystem->freedecal == numdecals)
12804 decal[decalsystem->freedecal] = decal[--numdecals];
12807 decalsystem->numdecals = numdecals;
12809 if (numdecals <= 0)
12811 // if there are no decals left, reset decalsystem
12812 R_DecalSystem_Reset(decalsystem);
12816 extern skinframe_t *decalskinframe;
12817 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12820 decalsystem_t *decalsystem = &ent->decalsystem;
12829 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12832 numdecals = decalsystem->numdecals;
12836 if (r_showsurfaces.integer)
12839 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12841 R_DecalSystem_Reset(decalsystem);
12845 // if the model is static it doesn't matter what value we give for
12846 // wantnormals and wanttangents, so this logic uses only rules applicable
12847 // to a model, knowing that they are meaningless otherwise
12848 if (ent == r_refdef.scene.worldentity)
12849 RSurf_ActiveWorldEntity();
12851 RSurf_ActiveModelEntity(ent, false, false, false);
12853 decalsystem->lastupdatetime = cl.time;
12854 decal = decalsystem->decals;
12856 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12858 // update vertex positions for animated models
12859 v3f = decalsystem->vertex3f;
12860 c4f = decalsystem->color4f;
12861 t2f = decalsystem->texcoord2f;
12862 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12864 if (!decal->color4ub[0][3])
12867 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12870 // update color values for fading decals
12871 if (decal->lived >= cl_decals_time.value)
12873 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12874 alpha *= (1.0f/255.0f);
12877 alpha = 1.0f/255.0f;
12879 c4f[ 0] = decal->color4ub[0][0] * alpha;
12880 c4f[ 1] = decal->color4ub[0][1] * alpha;
12881 c4f[ 2] = decal->color4ub[0][2] * alpha;
12883 c4f[ 4] = decal->color4ub[1][0] * alpha;
12884 c4f[ 5] = decal->color4ub[1][1] * alpha;
12885 c4f[ 6] = decal->color4ub[1][2] * alpha;
12887 c4f[ 8] = decal->color4ub[2][0] * alpha;
12888 c4f[ 9] = decal->color4ub[2][1] * alpha;
12889 c4f[10] = decal->color4ub[2][2] * alpha;
12892 t2f[0] = decal->texcoord2f[0][0];
12893 t2f[1] = decal->texcoord2f[0][1];
12894 t2f[2] = decal->texcoord2f[1][0];
12895 t2f[3] = decal->texcoord2f[1][1];
12896 t2f[4] = decal->texcoord2f[2][0];
12897 t2f[5] = decal->texcoord2f[2][1];
12899 // update vertex positions for animated models
12900 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12902 e = rsurface.modelelement3i + 3*decal->triangleindex;
12903 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12904 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12905 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12909 VectorCopy(decal->vertex3f[0], v3f);
12910 VectorCopy(decal->vertex3f[1], v3f + 3);
12911 VectorCopy(decal->vertex3f[2], v3f + 6);
12914 if (r_refdef.fogenabled)
12916 alpha = RSurf_FogVertex(v3f);
12917 VectorScale(c4f, alpha, c4f);
12918 alpha = RSurf_FogVertex(v3f + 3);
12919 VectorScale(c4f + 4, alpha, c4f + 4);
12920 alpha = RSurf_FogVertex(v3f + 6);
12921 VectorScale(c4f + 8, alpha, c4f + 8);
12932 r_refdef.stats.drawndecals += numtris;
12934 // now render the decals all at once
12935 // (this assumes they all use one particle font texture!)
12936 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);
12937 R_Mesh_ResetTextureState();
12938 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12939 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12940 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12941 GL_DepthMask(false);
12942 GL_DepthRange(0, 1);
12943 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12944 GL_DepthTest(true);
12945 GL_CullFace(GL_NONE);
12946 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12947 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12948 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12952 static void R_DrawModelDecals(void)
12956 // fade faster when there are too many decals
12957 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12958 for (i = 0;i < r_refdef.scene.numentities;i++)
12959 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12961 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12962 for (i = 0;i < r_refdef.scene.numentities;i++)
12963 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12964 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12966 R_DecalSystem_ApplySplatEntitiesQueue();
12968 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12969 for (i = 0;i < r_refdef.scene.numentities;i++)
12970 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12972 r_refdef.stats.totaldecals += numdecals;
12974 if (r_showsurfaces.integer)
12977 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12979 for (i = 0;i < r_refdef.scene.numentities;i++)
12981 if (!r_refdef.viewcache.entityvisible[i])
12983 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12984 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12988 extern cvar_t mod_collision_bih;
12989 void R_DrawDebugModel(void)
12991 entity_render_t *ent = rsurface.entity;
12992 int i, j, k, l, flagsmask;
12993 const msurface_t *surface;
12994 dp_model_t *model = ent->model;
12997 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12999 R_Mesh_ColorPointer(NULL, 0, 0);
13000 R_Mesh_ResetTextureState();
13001 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13002 GL_DepthRange(0, 1);
13003 GL_DepthTest(!r_showdisabledepthtest.integer);
13004 GL_DepthMask(false);
13005 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13007 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13011 qboolean cullbox = ent == r_refdef.scene.worldentity;
13012 const q3mbrush_t *brush;
13013 const bih_t *bih = &model->collision_bih;
13014 const bih_leaf_t *bihleaf;
13015 float vertex3f[3][3];
13016 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13018 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13020 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13022 switch (bihleaf->type)
13025 brush = model->brush.data_brushes + bihleaf->itemindex;
13026 if (brush->colbrushf && brush->colbrushf->numtriangles)
13028 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
13029 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);
13030 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
13033 case BIH_COLLISIONTRIANGLE:
13034 triangleindex = bihleaf->itemindex;
13035 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13036 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13037 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13038 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
13039 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);
13040 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
13042 case BIH_RENDERTRIANGLE:
13043 triangleindex = bihleaf->itemindex;
13044 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13045 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13046 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13047 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
13048 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);
13049 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
13055 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13057 if (r_showtris.integer || r_shownormals.integer)
13059 if (r_showdisabledepthtest.integer)
13061 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13062 GL_DepthMask(false);
13066 GL_BlendFunc(GL_ONE, GL_ZERO);
13067 GL_DepthMask(true);
13069 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13071 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13073 rsurface.texture = R_GetCurrentTexture(surface->texture);
13074 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13076 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
13077 if (r_showtris.value > 0)
13079 if (!rsurface.texture->currentlayers->depthmask)
13080 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13081 else if (ent == r_refdef.scene.worldentity)
13082 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13084 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13085 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
13086 R_Mesh_ColorPointer(NULL, 0, 0);
13087 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
13088 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13089 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
13090 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);
13091 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13094 if (r_shownormals.value < 0)
13096 qglBegin(GL_LINES);
13097 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13099 VectorCopy(rsurface.vertex3f + l * 3, v);
13100 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13101 qglVertex3f(v[0], v[1], v[2]);
13102 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
13103 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13104 qglVertex3f(v[0], v[1], v[2]);
13109 if (r_shownormals.value > 0)
13111 qglBegin(GL_LINES);
13112 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13114 VectorCopy(rsurface.vertex3f + l * 3, v);
13115 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13116 qglVertex3f(v[0], v[1], v[2]);
13117 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
13118 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13119 qglVertex3f(v[0], v[1], v[2]);
13123 qglBegin(GL_LINES);
13124 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13126 VectorCopy(rsurface.vertex3f + l * 3, v);
13127 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13128 qglVertex3f(v[0], v[1], v[2]);
13129 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
13130 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13131 qglVertex3f(v[0], v[1], v[2]);
13135 qglBegin(GL_LINES);
13136 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13138 VectorCopy(rsurface.vertex3f + l * 3, v);
13139 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13140 qglVertex3f(v[0], v[1], v[2]);
13141 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
13142 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13143 qglVertex3f(v[0], v[1], v[2]);
13150 rsurface.texture = NULL;
13154 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13155 int r_maxsurfacelist = 0;
13156 const msurface_t **r_surfacelist = NULL;
13157 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13159 int i, j, endj, flagsmask;
13160 dp_model_t *model = r_refdef.scene.worldmodel;
13161 msurface_t *surfaces;
13162 unsigned char *update;
13163 int numsurfacelist = 0;
13167 if (r_maxsurfacelist < model->num_surfaces)
13169 r_maxsurfacelist = model->num_surfaces;
13171 Mem_Free((msurface_t**)r_surfacelist);
13172 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13175 RSurf_ActiveWorldEntity();
13177 surfaces = model->data_surfaces;
13178 update = model->brushq1.lightmapupdateflags;
13180 // update light styles on this submodel
13181 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13183 model_brush_lightstyleinfo_t *style;
13184 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13186 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13188 int *list = style->surfacelist;
13189 style->value = r_refdef.scene.lightstylevalue[style->style];
13190 for (j = 0;j < style->numsurfaces;j++)
13191 update[list[j]] = true;
13196 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13200 R_DrawDebugModel();
13201 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13205 rsurface.uselightmaptexture = false;
13206 rsurface.texture = NULL;
13207 rsurface.rtlight = NULL;
13208 numsurfacelist = 0;
13209 // add visible surfaces to draw list
13210 for (i = 0;i < model->nummodelsurfaces;i++)
13212 j = model->sortedmodelsurfaces[i];
13213 if (r_refdef.viewcache.world_surfacevisible[j])
13214 r_surfacelist[numsurfacelist++] = surfaces + j;
13216 // update lightmaps if needed
13217 if (model->brushq1.firstrender)
13219 model->brushq1.firstrender = false;
13220 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13222 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13226 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13227 if (r_refdef.viewcache.world_surfacevisible[j])
13229 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13231 // don't do anything if there were no surfaces
13232 if (!numsurfacelist)
13234 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13237 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13238 GL_AlphaTest(false);
13240 // add to stats if desired
13241 if (r_speeds.integer && !skysurfaces && !depthonly)
13243 r_refdef.stats.world_surfaces += numsurfacelist;
13244 for (j = 0;j < numsurfacelist;j++)
13245 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13248 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13251 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13253 int i, j, endj, flagsmask;
13254 dp_model_t *model = ent->model;
13255 msurface_t *surfaces;
13256 unsigned char *update;
13257 int numsurfacelist = 0;
13261 if (r_maxsurfacelist < model->num_surfaces)
13263 r_maxsurfacelist = model->num_surfaces;
13265 Mem_Free((msurface_t **)r_surfacelist);
13266 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13269 // if the model is static it doesn't matter what value we give for
13270 // wantnormals and wanttangents, so this logic uses only rules applicable
13271 // to a model, knowing that they are meaningless otherwise
13272 if (ent == r_refdef.scene.worldentity)
13273 RSurf_ActiveWorldEntity();
13274 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13275 RSurf_ActiveModelEntity(ent, false, false, false);
13277 RSurf_ActiveModelEntity(ent, true, true, true);
13278 else if (depthonly)
13280 switch (vid.renderpath)
13282 case RENDERPATH_GL20:
13283 case RENDERPATH_CGGL:
13284 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13286 case RENDERPATH_GL13:
13287 case RENDERPATH_GL11:
13288 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13294 switch (vid.renderpath)
13296 case RENDERPATH_GL20:
13297 case RENDERPATH_CGGL:
13298 RSurf_ActiveModelEntity(ent, true, true, false);
13300 case RENDERPATH_GL13:
13301 case RENDERPATH_GL11:
13302 RSurf_ActiveModelEntity(ent, true, false, false);
13307 surfaces = model->data_surfaces;
13308 update = model->brushq1.lightmapupdateflags;
13310 // update light styles
13311 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13313 model_brush_lightstyleinfo_t *style;
13314 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13316 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13318 int *list = style->surfacelist;
13319 style->value = r_refdef.scene.lightstylevalue[style->style];
13320 for (j = 0;j < style->numsurfaces;j++)
13321 update[list[j]] = true;
13326 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13330 R_DrawDebugModel();
13331 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13335 rsurface.uselightmaptexture = false;
13336 rsurface.texture = NULL;
13337 rsurface.rtlight = NULL;
13338 numsurfacelist = 0;
13339 // add visible surfaces to draw list
13340 for (i = 0;i < model->nummodelsurfaces;i++)
13341 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13342 // don't do anything if there were no surfaces
13343 if (!numsurfacelist)
13345 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13348 // update lightmaps if needed
13352 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13357 R_BuildLightMap(ent, surfaces + j);
13362 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13364 R_BuildLightMap(ent, surfaces + j);
13365 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13366 GL_AlphaTest(false);
13368 // add to stats if desired
13369 if (r_speeds.integer && !skysurfaces && !depthonly)
13371 r_refdef.stats.entities_surfaces += numsurfacelist;
13372 for (j = 0;j < numsurfacelist;j++)
13373 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
13376 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13379 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13381 static texture_t texture;
13382 static msurface_t surface;
13383 const msurface_t *surfacelist = &surface;
13385 // fake enough texture and surface state to render this geometry
13387 texture.update_lastrenderframe = -1; // regenerate this texture
13388 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
13389 texture.currentskinframe = skinframe;
13390 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
13391 texture.offsetmapping = OFFSETMAPPING_OFF;
13392 texture.offsetscale = 1;
13393 texture.specularscalemod = 1;
13394 texture.specularpowermod = 1;
13396 surface.texture = &texture;
13397 surface.num_triangles = numtriangles;
13398 surface.num_firsttriangle = firsttriangle;
13399 surface.num_vertices = numvertices;
13400 surface.num_firstvertex = firstvertex;
13403 rsurface.texture = R_GetCurrentTexture(surface.texture);
13404 rsurface.uselightmaptexture = false;
13405 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13408 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)
13410 static msurface_t surface;
13411 const msurface_t *surfacelist = &surface;
13413 // fake enough texture and surface state to render this geometry
13414 surface.texture = texture;
13415 surface.num_triangles = numtriangles;
13416 surface.num_firsttriangle = firsttriangle;
13417 surface.num_vertices = numvertices;
13418 surface.num_firstvertex = firstvertex;
13421 rsurface.texture = R_GetCurrentTexture(surface.texture);
13422 rsurface.uselightmaptexture = false;
13423 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);